From f78c9307cc7ee1fa2e96eb964e9ace00a40809ca Mon Sep 17 00:00:00 2001 From: Matthew Wilkes Date: Fri, 24 May 2024 23:41:36 +0100 Subject: [PATCH] Improved OTA --- modules/app.py | 12 ++++++------ modules/app_components/tokens.py | 4 ++++ modules/async_helpers.py | 24 ++++++++++++++++++------ modules/firmware_apps/intro_app.py | 1 + modules/firmware_apps/pingpong_app.py | 2 ++ modules/firmware_apps/test_app.py | 2 +- modules/firmware_apps/tick_app.py | 1 + modules/frontboards/twentyfour.py | 1 + modules/main.py | 3 +++ modules/system/hexpansion/app.py | 1 + modules/system/launcher/app.py | 6 ++---- modules/system/notification/app.py | 1 + modules/system/ota/ota.py | 1 + modules/system/scheduler/__init__.py | 4 ++-- patches/micropython.diff | 2 +- sim/fakes/network.py | 1 + tildagon/partitions-tildagon.csv | 6 +++--- tildagon/sdkconfig.board | 2 ++ 18 files changed, 51 insertions(+), 23 deletions(-) diff --git a/modules/app.py b/modules/app.py index b7596d6..bd153f8 100644 --- a/modules/app.py +++ b/modules/app.py @@ -1,7 +1,6 @@ import asyncio import time -from perf_timer import PerfTimer from system.eventbus import eventbus from system.scheduler.events import RequestForegroundPopEvent @@ -19,13 +18,14 @@ async def run(self, render_update): while True: cur_time = time.ticks_ms() delta_ticks = time.ticks_diff(cur_time, last_time) - with PerfTimer(f"Updating {self}"): - self.update(delta_ticks) - await render_update() + if self.update(delta_ticks) is not False: + await render_update() + else: + await asyncio.sleep(0.05) last_time = cur_time - def update(self, delta): - pass + def update(self, delta: float) -> bool: + return False def draw(self, ctx): self.draw_overlays(ctx) diff --git a/modules/app_components/tokens.py b/modules/app_components/tokens.py index fc94373..717f0c9 100644 --- a/modules/app_components/tokens.py +++ b/modules/app_components/tokens.py @@ -28,6 +28,10 @@ "blue": (46, 173, 217), } +colors = { + name: (c[0] / 256.0, c[1] / 256.0, c[2] / 256.0) for (name, c) in colors.items() +} + ui_colors = {"background": colors["dark_green"], "label": (232, 230, 227)} diff --git a/modules/async_helpers.py b/modules/async_helpers.py index e943386..5ddbaf3 100644 --- a/modules/async_helpers.py +++ b/modules/async_helpers.py @@ -1,5 +1,6 @@ import asyncio import sys +import _thread if hasattr(sys.implementation, "_machine"): # MicroPython from threadsafe import Message @@ -27,6 +28,7 @@ def __iter__(self): # Thanks to https://github.com/peterhinch/micropython-async/blob/master/v3/docs/THREADING.md async def unblock(func, periodic_func, *args, **kwargs): def wrap(func, message, args, kwargs): + nonlocal running print("In thread") try: print(func, args, kwargs) @@ -34,18 +36,28 @@ def wrap(func, message, args, kwargs): except Exception as e: result = e print(result) + running = False message.set(result) # Run the blocking function. - # msg = Message() + running = True + + async def periodic(): + while running: + print("Periodic") + await periodic_func() + await asyncio.sleep(0.1) + + msg = Message() print("Starting thread") # _thread.start_new_thread(print, ("Test", )) - # tid = _thread.start_new_thread(wrap, (func, msg, args, kwargs)) + _thread.start_new_thread(wrap, (func, msg, args, kwargs)) # print(tid) # time.sleep(1) - result = func(*args, **kwargs) - print("async unblock") - await periodic_func() - # result = await msg.wait() + # result = func(*args, **kwargs) + # await periodic_func() + periodic = asyncio.create_task(periodic()) + result, _ = await asyncio.gather(msg.wait(), periodic) + print(result) if isinstance(result, Exception): raise result diff --git a/modules/firmware_apps/intro_app.py b/modules/firmware_apps/intro_app.py index 30cef19..72c5960 100644 --- a/modules/firmware_apps/intro_app.py +++ b/modules/firmware_apps/intro_app.py @@ -77,6 +77,7 @@ def update(self, delta): tildagonos.leds[i] = (0, 0, 0) tildagonos.leds.write() + return True def draw_background(self, ctx): ctx.gray(1 - min(1, self.time_elapsed)).rectangle(-120, -120, 240, 240).fill() diff --git a/modules/firmware_apps/pingpong_app.py b/modules/firmware_apps/pingpong_app.py index f8d0951..13e6b1a 100644 --- a/modules/firmware_apps/pingpong_app.py +++ b/modules/firmware_apps/pingpong_app.py @@ -43,6 +43,7 @@ def update(self, delta): if delta > 1000: print("sync pong") self.time_since_received = None + return True def draw(self, ctx): pass @@ -70,6 +71,7 @@ def update(self, delta): if delta > 1000: print("sync ping") self.time_since_received = None + return True def draw(self, ctx): pass diff --git a/modules/firmware_apps/test_app.py b/modules/firmware_apps/test_app.py index 3237d1c..25d1f4a 100644 --- a/modules/firmware_apps/test_app.py +++ b/modules/firmware_apps/test_app.py @@ -11,7 +11,7 @@ def __init__(self): ) def update(self, delta): - pass + return True def draw_background(self, ctx): ctx.gray(0).rectangle(-120, -120, 240, 240).fill() diff --git a/modules/firmware_apps/tick_app.py b/modules/firmware_apps/tick_app.py index cf70cbd..3567577 100644 --- a/modules/firmware_apps/tick_app.py +++ b/modules/firmware_apps/tick_app.py @@ -8,6 +8,7 @@ def __init__(self): def update(self, delta): self.acc_time += delta + return True def draw(self, ctx): if self.acc_time > 1000_000: diff --git a/modules/frontboards/twentyfour.py b/modules/frontboards/twentyfour.py index 36ca8f4..0285c28 100644 --- a/modules/frontboards/twentyfour.py +++ b/modules/frontboards/twentyfour.py @@ -32,6 +32,7 @@ async def background_task(self): 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]: diff --git a/modules/main.py b/modules/main.py index 287a37e..1a617ec 100644 --- a/modules/main.py +++ b/modules/main.py @@ -1,4 +1,5 @@ # main.py -- put your code here! +from esp32 import Partition from system.scheduler import scheduler from system.hexpansion.app import HexpansionManagerApp @@ -19,4 +20,6 @@ # Start notification handler scheduler.start_app(NotificationService(), always_on_top=True) +Partition.mark_app_valid_cancel_rollback() + scheduler.run_forever() diff --git a/modules/system/hexpansion/app.py b/modules/system/hexpansion/app.py index 81f64e8..c761c05 100644 --- a/modules/system/hexpansion/app.py +++ b/modules/system/hexpansion/app.py @@ -70,6 +70,7 @@ def close(): self.format_dialog_port = port eventbus.emit(RequestForegroundPushEvent(self)) + return True def draw(self, ctx): if self.format_dialog is not None: diff --git a/modules/system/launcher/app.py b/modules/system/launcher/app.py index dc4d697..dc8a6b0 100644 --- a/modules/system/launcher/app.py +++ b/modules/system/launcher/app.py @@ -3,6 +3,7 @@ from app import App from app_components.menu import Menu +from app_components import clear_background from perf_timer import PerfTimer from system.eventbus import eventbus from system.scheduler.events import RequestStartAppEvent, RequestForegroundPushEvent @@ -143,11 +144,8 @@ def back_handler(self): # return # self.set_menu("main") - def draw_background(self, ctx): - ctx.gray(0).rectangle(-120, -120, 240, 240).fill() - def draw(self, ctx): - self.draw_background(ctx) + clear_background(ctx) self.menu.draw(ctx) def update(self, delta): diff --git a/modules/system/notification/app.py b/modules/system/notification/app.py index df6184f..646378a 100644 --- a/modules/system/notification/app.py +++ b/modules/system/notification/app.py @@ -24,6 +24,7 @@ def update(self, delta): except Exception as e: print(e) continue + return any(notification._open for notification in self.notifications) def draw(self, ctx): for notification in self.notifications: diff --git a/modules/system/ota/ota.py b/modules/system/ota/ota.py index 67eef46..e6a4050 100644 --- a/modules/system/ota/ota.py +++ b/modules/system/ota/ota.py @@ -164,6 +164,7 @@ def progress(self, version, val): self.version = version self.progress_pct = val + self.status = f"{val} %" print(version, val) # window.progress_bar(window.get_next_line(), val) return True diff --git a/modules/system/scheduler/__init__.py b/modules/system/scheduler/__init__.py index da73882..5ada5cc 100644 --- a/modules/system/scheduler/__init__.py +++ b/modules/system/scheduler/__init__.py @@ -155,13 +155,13 @@ async def start_update_tasks(self, app): async def mark_update_finished(): # Unblock renderer self.render_needed.set() - await asyncio.sleep(0) + await asyncio.sleep(0.05) # If we're no longer foregounded, wait until it is before returning did_lose_focus = False while not self.app_is_foregrounded(app): did_lose_focus = True - await asyncio.sleep(0.100) + await asyncio.sleep(0.250) # Return control to the update task return did_lose_focus diff --git a/patches/micropython.diff b/patches/micropython.diff index bbfee44..b298e8b 100644 --- a/patches/micropython.diff +++ b/patches/micropython.diff @@ -1,5 +1,5 @@ diff --git a/ports/esp32/esp32_common.cmake b/ports/esp32/esp32_common.cmake -index 89e46f9cf..ed2cc007c 100644 +index e928fb439..fde5160a5 100644 --- a/ports/esp32/esp32_common.cmake +++ b/ports/esp32/esp32_common.cmake @@ -11,6 +11,9 @@ endif() diff --git a/sim/fakes/network.py b/sim/fakes/network.py index 452396b..772a01b 100644 --- a/sim/fakes/network.py +++ b/sim/fakes/network.py @@ -30,3 +30,4 @@ def status(self, mode=None): def config(self, a): return None + diff --git a/tildagon/partitions-tildagon.csv b/tildagon/partitions-tildagon.csv index 952b578..e84bf98 100644 --- a/tildagon/partitions-tildagon.csv +++ b/tildagon/partitions-tildagon.csv @@ -6,6 +6,6 @@ nvs, data, nvs, 0x9000, 0x4000, otadata, data, ota, 0xd000, 0x2000, phy_init, data, phy, 0xf000, 0x1000, -ota_0, app, ota_0, 0x10000, 0x210000, -ota_1, app, ota_1, 0x220000, 0x210000, -vfs, data, fat, 0x430000, 0x3d0000, +ota_0, app, ota_0, 0x10000, 0x270000, +ota_1, app, ota_1, 0x280000, 0x270000, +vfs, data, fat, 0x4f0000, 0x310000, diff --git a/tildagon/sdkconfig.board b/tildagon/sdkconfig.board index de57127..0b0d142 100644 --- a/tildagon/sdkconfig.board +++ b/tildagon/sdkconfig.board @@ -22,3 +22,5 @@ CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y CONFIG_APP_EXCLUDE_PROJECT_VER_VAR=n CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR=n CONFIG_APP_PROJECT_VER_FROM_CONFIG=y + +CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP=y