From d0b52a77f1183c63bf55a252e93de5e4632cab59 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Fri, 4 Mar 2022 14:40:09 +0000 Subject: [PATCH 1/7] Badger2040: List load/save --- micropython/examples/badger2040/list.py | 46 ++++++++++++++++++------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/micropython/examples/badger2040/list.py b/micropython/examples/badger2040/list.py index 1260fe058..a2846ca7c 100644 --- a/micropython/examples/badger2040/list.py +++ b/micropython/examples/badger2040/list.py @@ -5,19 +5,9 @@ # **** Put your list title and contents here ***** list_title = "Checklist" list_content = ["Badger", "Badger", "Badger", "Badger", "Badger", "Mushroom", "Mushroom", "Snake"] - list_states = [False] * len(list_content) +list_file = "checklist.txt" -try: - with open("checklist.txt", "r") as f: - list_content = f.read().split("\n") - list_title = list_content.pop(0) - for i in range(len(list_content)): - if list_content[i].endswith(" X"): - list_states[i] = True - list_content[i] = list_content[i][:-2] -except OSError: - pass # Global Constants WIDTH = badger2040.WIDTH @@ -39,6 +29,16 @@ LIST_HEIGHT = HEIGHT - LIST_START - LIST_PADDING - ARROW_HEIGHT +def save_list(): + with open(list_file, "w") as f: + f.write(list_title + "\n") + for i in range(len(list_content)): + list_item = list_content[i] + if list_states[i]: + list_item += " X" + f.write(list_item + "\n") + + # ------------------------------ # Drawing functions # ------------------------------ @@ -137,6 +137,7 @@ def draw_checkbox(x, y, size, background, foreground, thickness, tick, padding): # Global variables update = True +needs_save = False current_item = 0 items_per_page = 0 @@ -174,8 +175,7 @@ def draw_checkbox(x, y, size, background, foreground, thickness, tick, padding): # Button handling function def button(pin): - global update - global current_item + global update, current_item, needs_save if len(list_content) > 0 and not update: if pin == button_a: @@ -185,6 +185,7 @@ def button(pin): return if pin == button_b: list_states[current_item] = not list_states[current_item] + needs_save = True update = True return if pin == button_c: @@ -216,7 +217,26 @@ def button(pin): # Main program loop # ------------------------------ +try: + with open(list_file, "r") as f: + list_content = f.read().strip().split("\n") + list_title = list_content.pop(0) + list_states = [False] * len(list_content) + for i in range(len(list_content)): + list_content[i] = list_content[i].strip() + if list_content[i].endswith(" X"): + list_states[i] = True + list_content[i] = list_content[i][:-2] + +except OSError: + save_list() + + while True: + if needs_save: + save_list() + needs_save = False + if update: display.pen(15) display.clear() From 4496e3e7a20e3703e4afd9c29478f119540202ba Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Fri, 4 Mar 2022 14:58:52 +0000 Subject: [PATCH 2/7] Badger2040: Image file overlay toggle --- micropython/examples/badger2040/image.py | 36 ++++++++++++++---------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/micropython/examples/badger2040/image.py b/micropython/examples/badger2040/image.py index e426b47fe..d8956a273 100644 --- a/micropython/examples/badger2040/image.py +++ b/micropython/examples/badger2040/image.py @@ -58,6 +58,7 @@ image = bytearray(int(296 * 128 / 8)) current_image = 0 +show_info = True # Draw an overlay box with a given message within it @@ -97,22 +98,24 @@ def show_image(n): name = file.split(".")[0] open("images/{}".format(file), "r").readinto(image) display.image(image) - name_length = display.measure_text(name, 0.5) - display.pen(0) - display.rectangle(0, HEIGHT - 21, name_length + 11, 21) - display.pen(15) - display.rectangle(0, HEIGHT - 20, name_length + 10, 20) - display.pen(0) - display.text(name, 5, HEIGHT - 10, 0.5) - for i in range(TOTAL_IMAGES): - x = 286 - y = int((128 / 2) - (TOTAL_IMAGES * 10 / 2) + (i * 10)) + if show_info: + name_length = display.measure_text(name, 0.5) display.pen(0) - display.rectangle(x, y, 8, 8) - if current_image != i: - display.pen(15) - display.rectangle(x + 1, y + 1, 6, 6) + display.rectangle(0, HEIGHT - 21, name_length + 11, 21) + display.pen(15) + display.rectangle(0, HEIGHT - 20, name_length + 10, 20) + display.pen(0) + display.text(name, 5, HEIGHT - 10, 0.5) + + for i in range(TOTAL_IMAGES): + x = 286 + y = int((128 / 2) - (TOTAL_IMAGES * 10 / 2) + (i * 10)) + display.pen(0) + display.rectangle(x, y, 8, 8) + if current_image != i: + display.pen(15) + display.rectangle(x + 1, y + 1, 6, 6) display.update() @@ -137,7 +140,10 @@ def show_image(n): if current_image < TOTAL_IMAGES - 1: current_image += 1 show_image(current_image) - if button_a.value() or button_b.value() or button_c.value(): + if button_a.value(): + show_info = not show_info + show_image(current_image) + if button_b.value() or button_c.value(): display.pen(15) display.clear() draw_overlay("To add images connect Badger2040 to a PC, load up Thonny, and see readme.txt in images/", WIDTH - OVERLAY_BORDER, HEIGHT - OVERLAY_BORDER, OVERLAY_SPACING, 0.5) From 3756f0b7073692219d0f537d7f7d432cee6feaab Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Fri, 4 Mar 2022 15:12:29 +0000 Subject: [PATCH 3/7] Badger2040: Ebook font size & style controls --- micropython/examples/badger2040/ebook.py | 47 ++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/micropython/examples/badger2040/ebook.py b/micropython/examples/badger2040/ebook.py index 558526a1b..6a2db0d2a 100644 --- a/micropython/examples/badger2040/ebook.py +++ b/micropython/examples/badger2040/ebook.py @@ -30,15 +30,18 @@ ARROW_PADDING = 2 TEXT_PADDING = 4 -TEXT_SPACING = 20 + TEXT_SIZE = 0.5 +TEXT_SPACING = int(34 * TEXT_SIZE) TEXT_WIDTH = WIDTH - TEXT_PADDING - TEXT_PADDING - ARROW_WIDTH - +FONTS = ["sans", "gothic", "cursive", "serif"] +FONT_THICKNESSES = [2, 1, 1, 2] # ------------------------------ # Drawing functions # ------------------------------ + # Draw a upward arrow def draw_up(x, y, width, height, thickness, padding): border = (thickness // 4) + padding @@ -79,6 +82,8 @@ def draw_frame(): # Global variables next_page = True prev_page = False +change_font_size = False +change_font = False last_offset = 0 current_page = 0 @@ -90,6 +95,9 @@ def draw_frame(): button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN) button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN) +button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN) +button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN) + # Set up the activity LED led = machine.Pin(badger2040.PIN_LED, machine.Pin.OUT) @@ -98,7 +106,7 @@ def draw_frame(): # Button handling function def button(pin): - global next_page, prev_page + global next_page, prev_page, change_font_size, change_font if pin == button_down: next_page = True @@ -106,10 +114,18 @@ def button(pin): if pin == button_up: prev_page = True + if pin == button_a: + change_font_size = True + + if pin == button_b: + change_font = True + # Register the button handling function with the buttons button_down.irq(trigger=machine.Pin.IRQ_RISING, handler=button) button_up.irq(trigger=machine.Pin.IRQ_RISING, handler=button) +button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=button) +button_b.irq(trigger=machine.Pin.IRQ_RISING, handler=button) # ------------------------------ @@ -122,6 +138,7 @@ def render_page(): pos = ebook.tell() next_pos = pos add_newline = False + display.font(FONTS[0]) while True: # Read a full line and split it into words @@ -168,7 +185,7 @@ def render_page(): # Yes, so write out the line prior to the append print(line) display.pen(0) - display.thickness(2) + display.thickness(FONT_THICKNESSES[0]) display.text(line, TEXT_PADDING, (row * TEXT_SPACING) + (TEXT_SPACING // 2) + TEXT_PADDING, TEXT_SIZE) # Clear the line and move on to the next row @@ -231,4 +248,26 @@ def render_page(): render_page() prev_page = False # Clear the prev page button flag + if change_font_size: + TEXT_SIZE += 0.1 + if TEXT_SIZE > 0.8: + TEXT_SIZE = 0.5 + TEXT_SPACING = int(34 * TEXT_SIZE) + offsets = [0] + ebook.seek(0) + current_page = 1 + draw_frame() + render_page() + change_font_size = False + + if change_font: + FONTS.append(FONTS.pop(0)) + FONT_THICKNESSES.append(FONT_THICKNESSES.pop(0)) + offsets = [0] + ebook.seek(0) + current_page = 1 + draw_frame() + render_page() + change_font = False + time.sleep(0.1) From e62b3a8fc83e7e2e70209e45657238be182be0e8 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Fri, 4 Mar 2022 15:13:32 +0000 Subject: [PATCH 4/7] Badger2040: Move assets & builtin tooling to examples dir --- .../289-0-wind-in-the-willows-abridged.txt | 2 +- .../badger2040/assets/badge_image.png | Bin .../badger2040/assets/badgerpunk.png | Bin .../badger2040/assets/boot.py | 0 .../badger2040/assets/launchericons.png | Bin .../badger2040/micropython-builtins.cmake | 18 +++++++++--------- .../modules/badger2040-micropython.cmake | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) rename micropython/{modules => examples}/badger2040/assets/289-0-wind-in-the-willows-abridged.txt (97%) rename micropython/{modules => examples}/badger2040/assets/badge_image.png (100%) rename micropython/{modules => examples}/badger2040/assets/badgerpunk.png (100%) rename micropython/{modules => examples}/badger2040/assets/boot.py (100%) rename micropython/{modules => examples}/badger2040/assets/launchericons.png (100%) rename micropython/{modules => examples}/badger2040/micropython-builtins.cmake (65%) diff --git a/micropython/modules/badger2040/assets/289-0-wind-in-the-willows-abridged.txt b/micropython/examples/badger2040/assets/289-0-wind-in-the-willows-abridged.txt similarity index 97% rename from micropython/modules/badger2040/assets/289-0-wind-in-the-willows-abridged.txt rename to micropython/examples/badger2040/assets/289-0-wind-in-the-willows-abridged.txt index ec5e9158e..f6243fd9b 100644 --- a/micropython/modules/badger2040/assets/289-0-wind-in-the-willows-abridged.txt +++ b/micropython/examples/badger2040/assets/289-0-wind-in-the-willows-abridged.txt @@ -1,4 +1,4 @@ -The Project Gutenberg eBook of The Wind in the Willows, by Kenneth Grahame +The Project Gutenberg eBook of The Wind in the Willows, by Kenneth Grahame This eBook is for the use of anyone anywhere in the United States and most other parts of the world at no cost and with almost no restrictions diff --git a/micropython/modules/badger2040/assets/badge_image.png b/micropython/examples/badger2040/assets/badge_image.png similarity index 100% rename from micropython/modules/badger2040/assets/badge_image.png rename to micropython/examples/badger2040/assets/badge_image.png diff --git a/micropython/modules/badger2040/assets/badgerpunk.png b/micropython/examples/badger2040/assets/badgerpunk.png similarity index 100% rename from micropython/modules/badger2040/assets/badgerpunk.png rename to micropython/examples/badger2040/assets/badgerpunk.png diff --git a/micropython/modules/badger2040/assets/boot.py b/micropython/examples/badger2040/assets/boot.py similarity index 100% rename from micropython/modules/badger2040/assets/boot.py rename to micropython/examples/badger2040/assets/boot.py diff --git a/micropython/modules/badger2040/assets/launchericons.png b/micropython/examples/badger2040/assets/launchericons.png similarity index 100% rename from micropython/modules/badger2040/assets/launchericons.png rename to micropython/examples/badger2040/assets/launchericons.png diff --git a/micropython/modules/badger2040/micropython-builtins.cmake b/micropython/examples/badger2040/micropython-builtins.cmake similarity index 65% rename from micropython/modules/badger2040/micropython-builtins.cmake rename to micropython/examples/badger2040/micropython-builtins.cmake index 0473f27a3..b5d73b851 100644 --- a/micropython/modules/badger2040/micropython-builtins.cmake +++ b/micropython/examples/badger2040/micropython-builtins.cmake @@ -42,12 +42,12 @@ convert_image(usermod_badger2040 launchericons) convert_raw(usermod_badger2040 289-0-wind-in-the-willows-abridged.txt witw) copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/assets/boot.py boot) -copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/../../examples/badger2040/launcher.py _launcher) -copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/../../examples/badger2040/clock.py _clock) -copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/../../examples/badger2040/fonts.py _fonts) -copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/../../examples/badger2040/ebook.py _ebook) -copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/../../examples/badger2040/image.py _image) -copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/../../examples/badger2040/list.py _list) -copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/../../examples/badger2040/badge.py _badge) -copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/../../examples/badger2040/help.py _help) -copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/../../examples/badger2040/info.py _info) \ No newline at end of file +copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/launcher.py _launcher) +copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/clock.py _clock) +copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/fonts.py _fonts) +copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/ebook.py _ebook) +copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/image.py _image) +copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/list.py _list) +copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/badge.py _badge) +copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/help.py _help) +copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/info.py _info) diff --git a/micropython/modules/badger2040-micropython.cmake b/micropython/modules/badger2040-micropython.cmake index 663b8497a..fd3f12fc8 100644 --- a/micropython/modules/badger2040-micropython.cmake +++ b/micropython/modules/badger2040-micropython.cmake @@ -31,6 +31,6 @@ include(breakout_icp10125/micropython) include(breakout_scd41/micropython) include(badger2040/micropython) -include(badger2040/micropython-builtins) +include(micropython/examples/badger2040/micropython-builtins) include(plasma/micropython) -include(ulab/code/micropython) \ No newline at end of file +include(ulab/code/micropython) From cbf330a1c70f649305532b659e0924bf12c7bce0 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Fri, 4 Mar 2022 15:27:28 +0000 Subject: [PATCH 5/7] Badger2040: Drop from regular MicroPython build --- micropython/modules/micropython.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/micropython/modules/micropython.cmake b/micropython/modules/micropython.cmake index 72b8a2da6..7f554695a 100644 --- a/micropython/modules/micropython.cmake +++ b/micropython/modules/micropython.cmake @@ -37,7 +37,7 @@ include(pico_display/micropython) include(pico_display_2/micropython) include(pico_explorer/micropython) include(pico_wireless/micropython) -include(badger2040/micropython) + include(plasma/micropython) include(hub75/micropython) include(ulab/code/micropython) From ddf5f7631e8878cdffc398afc0874d5a7c10ead0 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Fri, 4 Mar 2022 15:42:47 +0000 Subject: [PATCH 6/7] Badger2040: Use book.txt for ebook example --- micropython/examples/badger2040/ebook.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/micropython/examples/badger2040/ebook.py b/micropython/examples/badger2040/ebook.py index 6a2db0d2a..0ebdf4075 100644 --- a/micropython/examples/badger2040/ebook.py +++ b/micropython/examples/badger2040/ebook.py @@ -3,12 +3,19 @@ import time import gc + +# **** Put the name of your text file here ***** +text_file = "book.txt" # File must be on the MicroPython device + + try: - open("witw.txt", "r") + open(text_file, "r") except OSError: try: + # If the specified file doesn't exist, + # pre-populate with Wind In The Willows import witw - open("witw.txt", "wb").write(witw.data()) + open(text_file, "wb").write(witw.data()) del witw except ImportError: pass @@ -16,10 +23,6 @@ gc.collect() - -# **** Put the name of your text file here ***** -text_file = "witw.txt" # File must be on the MicroPython device - # Global Constants WIDTH = badger2040.WIDTH HEIGHT = badger2040.HEIGHT From 04ff3023d9aff9c4d65d1579cb858b4ee9e0b0ad Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Fri, 4 Mar 2022 16:47:05 +0000 Subject: [PATCH 7/7] Badger2040: Improve clock * Toggle into time-set mode with B * Move to date/time parts with A/C * Change values with up/down * Centered clock so it looks nicer --- micropython/examples/badger2040/clock.py | 130 +++++++++++++++++++++-- 1 file changed, 120 insertions(+), 10 deletions(-) diff --git a/micropython/examples/badger2040/clock.py b/micropython/examples/badger2040/clock.py index ee7f8ac99..a74d2ee0a 100644 --- a/micropython/examples/badger2040/clock.py +++ b/micropython/examples/badger2040/clock.py @@ -1,30 +1,140 @@ import time +import machine import badger2040 -from machine import RTC -rtc = RTC() + +rtc = machine.RTC() screen = badger2040.Badger2040() screen.update_speed(badger2040.UPDATE_TURBO) screen.font("gothic") -year, month, day, wd, hour, minute, second, _ = rtc.datetime() +cursors = ["year", "month", "day", "hour", "minute"] +set_clock = False +cursor = 0 +last = 0 -if (year, month, day) == (2021, 1, 1): - rtc.datetime((2022, 2, 25, 3, 12, 0, 0, 0)) +# Set up the buttons +button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN) +button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN) -while True: - year, month, day, wd, hour, minute, second, _ = rtc.datetime() +button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN) +button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN) +button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN) + + +# Button handling function +def button(pin): + global last, set_clock, cursor, year, month, day, hour, minute + + time.sleep(0.05) + if not pin.value(): + return + + adjust = 0 + changed = False + + if pin == button_b: + set_clock = not set_clock + changed = True + if not set_clock: + rtc.datetime((year, month, day, 0, hour, minute, second, 0)) + + if set_clock: + if pin == button_c: + cursor += 1 + cursor %= len(cursors) + + if pin == button_a: + cursor -= 1 + cursor %= len(cursors) + + if pin == button_up: + adjust = 1 + + if pin == button_down: + adjust = -1 + + if cursors[cursor] == "year": + year += adjust + year = max(year, 2022) + if cursors[cursor] == "month": + month += adjust + month = min(max(month, 1), 12) + if cursors[cursor] == "day": + day += adjust + day = min(max(day, 1), 31) + if cursors[cursor] == "hour": + hour += adjust + hour %= 60 + if cursors[cursor] == "minute": + minute += adjust + minute %= 60 + + if set_clock or changed: + draw_clock() + + +# Register the button handling function with the buttons +button_down.irq(trigger=machine.Pin.IRQ_RISING, handler=button) +button_up.irq(trigger=machine.Pin.IRQ_RISING, handler=button) +button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=button) +button_b.irq(trigger=machine.Pin.IRQ_RISING, handler=button) +button_c.irq(trigger=machine.Pin.IRQ_RISING, handler=button) + + +def draw_clock(): hms = "{:02}:{:02}:{:02}".format(hour, minute, second) ymd = "{:04}/{:02}/{:02}".format(year, month, day) + hms_width = screen.measure_text(hms, 1.8) + hms_offset = int((badger2040.WIDTH / 2) - (hms_width / 2)) + h_width = screen.measure_text(hms[0:2], 1.8) + mi_width = screen.measure_text(hms[3:5], 1.8) + mi_offset = screen.measure_text(hms[0:3], 1.8) + + ymd_width = screen.measure_text(ymd, 1.0) + ymd_offset = int((badger2040.WIDTH / 2) - (ymd_width / 2)) + y_width = screen.measure_text(ymd[0:4], 1.0) + m_width = screen.measure_text(ymd[5:7], 1.0) + m_offset = screen.measure_text(ymd[0:5], 1.0) + d_width = screen.measure_text(ymd[8:10], 1.0) + d_offset = screen.measure_text(ymd[0:8], 1.0) + screen.pen(15) screen.clear() screen.pen(0) screen.thickness(5) - screen.text(hms, 0, 40, 1.8) + screen.text(hms, hms_offset, 40, 1.8) screen.thickness(3) - screen.text(ymd, 0, 100, 1.0) + screen.text(ymd, ymd_offset, 100, 1.0) + + if set_clock: + if cursors[cursor] == "year": + screen.line(ymd_offset, 120, ymd_offset + y_width, 120) + if cursors[cursor] == "month": + screen.line(ymd_offset + m_offset, 120, ymd_offset + m_offset + m_width, 120) + if cursors[cursor] == "day": + screen.line(ymd_offset + d_offset, 120, ymd_offset + d_offset + d_width, 120) + + if cursors[cursor] == "hour": + screen.line(hms_offset, 70, hms_offset + h_width, 70) + if cursors[cursor] == "minute": + screen.line(hms_offset + mi_offset, 70, hms_offset + mi_offset + mi_width, 70) screen.update() - time.sleep(0.5) + +year, month, day, wd, hour, minute, second, _ = rtc.datetime() + +if (year, month, day) == (2021, 1, 1): + rtc.datetime((2022, 2, 29, 3, 12, 0, 0, 0)) + +last_second = second + +while True: + if not set_clock: + year, month, day, wd, hour, minute, second, _ = rtc.datetime() + if second != last_second: + draw_clock() + last_second = second + time.sleep(0.1)