From b9f2917b1e22371a5c917bf2cdc195fea753249e Mon Sep 17 00:00:00 2001 From: Matthew Wilkes Date: Sun, 26 May 2024 18:18:57 +0100 Subject: [PATCH 1/2] Add automatic provisioning of the frontboard, from mpy files in github TODO: This currently still builds the files into the firmware, the github action needs changing to mpy-cross these independently --- .github/workflows/build.yml | 2 ++ modules/app_components/tokens.py | 6 ++++ modules/frontboards/__init__.py | 22 +++++++++++++++ modules/frontboards/twentyfour.py | 43 ----------------------------- modules/lib/requests/__init__.mpy | Bin 2380 -> 0 bytes modules/lib/urequests.mpy | Bin 101 -> 0 bytes modules/main.py | 44 +++++++++++++++++++++++++----- 7 files changed, 67 insertions(+), 50 deletions(-) delete mode 100644 modules/frontboards/twentyfour.py delete mode 100644 modules/lib/requests/__init__.mpy delete mode 100644 modules/lib/urequests.mpy diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f637456..67eb951 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -68,6 +68,8 @@ jobs: micropython/ports/esp32/build-tildagon/partition_table/partition-table.bin micropython/ports/esp32/build-tildagon/ota_data_initial.bin micropython/ports/esp32/build-tildagon/tildagon.txt + micropython/ports/esp32/build-tildagon/frozen_mpy/frontboards/TwentyFour/app.mpy + micropython/ports/esp32/build-tildagon/frozen_mpy/frontboards/TwentyFour/tokens.mpy - name: Create latest release for tags uses: "marvinpinto/action-automatic-releases@latest" if: github.event_name == 'push' diff --git a/modules/app_components/tokens.py b/modules/app_components/tokens.py index df440a8..93a5b7f 100644 --- a/modules/app_components/tokens.py +++ b/modules/app_components/tokens.py @@ -52,3 +52,9 @@ def clear_background(ctx): def set_color(ctx, color): ctx.rgb(*ui_colors.get(color, colors.get(color, color))) + + +try: + from frontboard.tokens import * # noqa: F403 +except ImportError: + pass diff --git a/modules/frontboards/__init__.py b/modules/frontboards/__init__.py index 69513cd..b8c6210 100644 --- a/modules/frontboards/__init__.py +++ b/modules/frontboards/__init__.py @@ -1,5 +1,27 @@ from app import App +from system.hexpansion.util import read_hexpansion_header, get_hexpansion_block_devices +import vfs class FrontBoard(App): year: int + + +def mount_frontboard(i2c, readonly=True): + header = read_hexpansion_header(i2c, eeprom_addr=0x57) + if header is None: + return False + + try: + eep, partition = get_hexpansion_block_devices(i2c, header, addr=0x57) + except Exception: + return False + + mountpoint = "/frontboard" + + try: + vfs.mount(partition, mountpoint, readonly=readonly) + except OSError: + return False + + return True diff --git a/modules/frontboards/twentyfour.py b/modules/frontboards/twentyfour.py deleted file mode 100644 index 0285c28..0000000 --- a/modules/frontboards/twentyfour.py +++ /dev/null @@ -1,43 +0,0 @@ -import asyncio - -import display -from events.input import Button, BUTTON_TYPES, ButtonDownEvent, ButtonUpEvent -from system.eventbus import eventbus -from tildagonos import tildagonos -from . import FrontBoard - - -BUTTONS = { - "A": Button("A", "TwentyTwentyFour", BUTTON_TYPES["UP"]), - "B": Button("B", "TwentyTwentyFour", BUTTON_TYPES["RIGHT"]), - "C": Button("C", "TwentyTwentyFour", BUTTON_TYPES["CONFIRM"]), - "D": Button("D", "TwentyTwentyFour", BUTTON_TYPES["DOWN"]), - "E": Button("E", "TwentyTwentyFour", BUTTON_TYPES["LEFT"]), - "F": Button("F", "TwentyTwentyFour", BUTTON_TYPES["CANCEL"]), -} - - -class TwentyTwentyFour(FrontBoard): - BUTTON_PINS = { - BUTTONS["A"]: (0x5A, 0, (1 << 6)), - BUTTONS["B"]: (0x5A, 0, (1 << 7)), - BUTTONS["C"]: (0x59, 0, (1 << 0)), - BUTTONS["D"]: (0x59, 0, (1 << 1)), - BUTTONS["E"]: (0x59, 0, (1 << 2)), - BUTTONS["F"]: (0x59, 0, (1 << 3)), - } - - async def background_task(self): - display.gfx_init() - - button_states = {button: False for button in self.BUTTON_PINS.keys()} - while True: - tildagonos.read_egpios() - for button, pin in self.BUTTON_PINS.items(): - button_down = not tildagonos.check_egpio_state(pin, readgpios=False) - if button_down and not button_states[button]: - await eventbus.emit_async(ButtonDownEvent(button=button)) - if not button_down and button_states[button]: - await eventbus.emit_async(ButtonUpEvent(button=button)) - button_states[button] = button_down - await asyncio.sleep(0.01) diff --git a/modules/lib/requests/__init__.mpy b/modules/lib/requests/__init__.mpy deleted file mode 100644 index ee445f59dfe98d63f50b9bd4e4c8334fddd29002..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2380 zcmZWpU2_`O89ppxg|LK|Wwk;Qk~VNy5c)tum^wJNC0JyTki`llRc<|-^|CTF5=(cN zCaNd#vYyN&o#~J0T`!TWBvwA^x-;!e+9sWjFIs2D%75rpE_-$*HTHBEIPZDh=Y8I< zGpylY;-_Rxm4DfmHC;;xLZjKx1!1;z04{smnj*a;>wwshwU*MbeRFmWc+UgC z!X(+g*Jz5G)M$XtBy}$-3im`!PN#t93?#Cm){vM7?*lVD;PljWy_Es|)}dtpuJ368 z%K-Ymtc$gp+Gy@7fUd0PR)tD+Bfqo;`p-+CG+Eah`?Av3fmc$ROi8L z(*axFSg)?<)=NUQR1tEeV*Yj&kh%OuRk*!=I}hkz$!cTwK-gDmGN9j8#g=d`J+8?r zatd`t)0^VH49udtfNXHn)Bc5~G=Znq-fwBB_W{p<2Xr2qJ~L|O%=yk`{8qjSXiXRO zwkAlHa=$8zR*bhUi#1u*fZH;FyO3YvKxf9?vV`5`^-2}sEz}EM-mC&oOVp)0@RXOT zxdP~~$$PSnq_})3U(JIsu8QvhLT;i2jplve6(mur%Qbrry4=)3=YiXvf%~l7Jw>c( zfEEPQmDW(2f&daTSBRFXv}9F30R8*2URP=WZ>xL2T@!T?jaf&9?*q5k*6YA~G3k+( zsA{rs(Mu;`CX~+g&bA<$ery-ut_SaD&}Ll&ODIfH8^0EHln=P*&8F6FwG>sCYYfV( zE0VI8VF2!nXiNfq3)N~lF+YnY3UH4#>%{KL!>Oo7+Fk-8<*N|-e zgw>`+3076HsqM<@O#Xa08AhtNoA1aq%S~MP|34|fd(YDXSO2T61H7-KoE4ox${TX6 zp`y&F5T>c<%z>;k|CAOkuQ>=cfVB^BeKr z%7TM-B{4dYbkg(59y*zH(WxX(r<1+(RicN^@sj&d&`mq*Ol`6D_D7yN%3$FpEtf` zcp@>_^}qN4 zwlN#pX7iEB6D*^gk(wO!%SiCASTID1pC&WH6-eCpVx!?4U95goBL7t_blu;wxG+=4Op)J^=z(I2}?PP~Ov)U}cA!_Kev}336`yONl z;NZhebhE3GAVm#B%0H5JumNqbNuo- zSF+I_=(C_>VKvSUTL>IRSKH+}H;&=3mCeR*WMrwwR#Czcf11mYZ^+g=VMpKy6@Hv{ z{K=;EBH9sm_j7L5zPhcbb=&MCD@Q4ZmD0X?Y~mk{&$;%Iu*$NdHhPJyz|kLBaP)$1 zrw>>h0$Q5ZU?z^vypc3ugD^-9@Mwo@5J?164)b5!3ffRV4E}&tgq9KPY@&6Hq2-RB zGycu3z@WKFu_%5V>7DCvw_q@gzu5ZGd1P1bdbhxKCs>? z68bv3LRP~*IA)caT}1DK%VxDF8>igvMXs|3FP_&hI{_!C$uxj89Nx+np1>faQ`k=S z$peg46fTjj?#a<(+sxKTCmce< zV&E8L0@H9D{mwwz+Wj)h$OL8~Bk@v)IWZR9iK20cgyy=HL*t5x{zYtbzG!@6$-j;! li^d5;7hXqGMdK@kUU?l&7ma5K{mJX-)uQodguZ!!{ugTLcohHu diff --git a/modules/lib/urequests.mpy b/modules/lib/urequests.mpy deleted file mode 100644 index 8677c9b5bf5731806331ed76eb794c64d859abc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101 zcmeZeW02=ykSHxmEi6qfE-BV4sAS;hGSIWoGhmPvfQd4Q#mASW78Pga=f%e}a3q$L y6frdFH}WuWF(xRaBp5M>F$*w>u?8kHHcBXRF|#E&xHbezvm6v+-?+hqDH#Ar)*0IX diff --git a/modules/main.py b/modules/main.py index d0c9958..660a25f 100644 --- a/modules/main.py +++ b/modules/main.py @@ -1,18 +1,41 @@ # main.py -- put your code here! from esp32 import Partition +import machine +import os -from system.scheduler import scheduler -from system.hexpansion.app import HexpansionManagerApp -from system.patterndisplay.app import PatternDisplay -from system.notification.app import NotificationService -from system.launcher.app import Launcher from system.power.handler import PowerEventHandler +import display +import frontboards +import tildagonos -from frontboards.twentyfour import TwentyTwentyFour + +tildagonos.tildagonos.init_gpio() +display.gfx_init() # Start front-board interface -scheduler.start_app(TwentyTwentyFour()) + +fb_i2c = machine.I2C(0) +frontboard = 0x57 in fb_i2c.scan() +if frontboard: + # We have a frontboard, try to mount it + mounted = frontboards.mount_frontboard(fb_i2c) + print(f"Frontboard mounted {mounted}") + if not mounted or "app.mpy" not in os.listdir("/frontboard"): + # Provision the board if not mountable + import provision_fb + + provision_fb.populate_fb() + + +# Do main imports after mounting the frontboard so they can +# import the year's design tokens +from system.scheduler import scheduler # noqa: E402 +from system.hexpansion.app import HexpansionManagerApp # noqa: E402 +from system.patterndisplay.app import PatternDisplay # noqa: E402 +from system.notification.app import NotificationService # noqa: E402 +from system.launcher.app import Launcher # noqa: E402 + # Start expansion interface scheduler.start_app(HexpansionManagerApp()) @@ -28,6 +51,13 @@ PowerEventHandler.RegisterDefaultCallbacks(PowerEventHandler) +if frontboard: + # Import the interface and start the app + import frontboard.app + + scheduler.start_app(frontboard.app.__app_export__()) + + Partition.mark_app_valid_cancel_rollback() scheduler.run_forever() From 54d9b04b816f4929a3cca6928b6480c71c9cd542 Mon Sep 17 00:00:00 2001 From: Matthew Wilkes Date: Thu, 30 May 2024 11:34:22 +0100 Subject: [PATCH 2/2] improve fb provisioning --- modules/provision_fb.py | 91 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 modules/provision_fb.py diff --git a/modules/provision_fb.py b/modules/provision_fb.py new file mode 100644 index 0000000..b8686af --- /dev/null +++ b/modules/provision_fb.py @@ -0,0 +1,91 @@ +from machine import I2C +from system.hexpansion.util import get_hexpansion_block_devices, HexpansionHeader +import vfs +import wifi +import display + +base = "/template" + +""" +import os, wifi, requests +os.mkdir("/template") +wifi.connect("emf2024", "badge", "badge") +wifi.wait() +for filename in ["tokens.mpy", "app.mpy"]: + with open(f"/template/{filename}", "wb") as fb_file: + data = requests.get(f"https://0d3d512069d3.ngrok.app/{filename}") + print(data.status_code) + fb_file.write(data.content) + print(fb_file.tell()) +""" + + +def status(msg=""): + try: + ctx = display.get_ctx() + ctx.rgb(0, 0, 0).rectangle(-120, -120, 240, 240).fill() + ctx.text_align = ctx.CENTER + ctx.font_size = 18.0 + ctx.rgb(1, 1, 1).move_to(0, 0).text("Provisioning ...") + ctx.rgb(1, 0, 0).move_to(0, 20).text(msg) + display.end_frame(ctx) + except Exception: + pass + + +def populate_fb(): + status() + # Ensure the board isn't mounted + mountpoint = "/frontboard" + + try: + vfs.umount(mountpoint) + except OSError: + pass + + port = 0 + addr = 0x57 + i2c = I2C(port) + wifi.connect() + + status("Header") + + h = HexpansionHeader( + manifest_version="2024", + fs_offset=32, + eeprom_page_size=32, + eeprom_total_size=1024 * 8, + vid=0xBAD3, + pid=0x2400, + unique_id=0x0, + friendly_name="TwentyTwentyFour", + ) + + status("Writing EEPROM") + # Write header to 0x00 of the eeprom + i2c.writeto(addr, bytes([0, 0]) + h.to_bytes()) + + _, partition = get_hexpansion_block_devices(i2c, h, addr) + + success = True + + status("Creating filesystem") + + vfs.VfsLfs2.mkfs(partition) + vfs.mount(partition, mountpoint, readonly=False) + + for filename in ["tokens.mpy", "app.mpy"]: + with open(f"{mountpoint}/{filename}", "wb") as fb_file: + with open(f"{base}/{filename}", "rb") as template_file: + fb_file.write(template_file.read()) + if fb_file.tell() != template_file.tell(): + status("Failed write") + success = False + + if not success: + raise ValueError("Retry") + + status("Remounting") + vfs.umount(mountpoint) + vfs.mount(partition, mountpoint, readonly=True) + status("Done")