diff --git a/micropython b/micropython index d112004..df61f43 160000 --- a/micropython +++ b/micropython @@ -1 +1 @@ -Subproject commit d11200432c211fc9e413c74eace1308c1c5e9ff1 +Subproject commit df61f43d562ec33388bdb27b07fb6f0bbdbe8b8b diff --git a/tools/wasptool b/tools/wasptool index 1897915..322ff0b 100755 --- a/tools/wasptool +++ b/tools/wasptool @@ -44,7 +44,8 @@ def unsync(c): process too early then the sendline will not have completed. """ c.sendline('wasp.system.run()') - c.expect('Watch is running, use Ctrl-C to stop') + c.expect(['Watch is running, use Ctrl-C to stop', + 'Watch already running in the background']) c.send('\x18') def paste(c, f, verbose=False, chunk=None): diff --git a/wasp/boards/pinetime/watch.py.in b/wasp/boards/pinetime/watch.py.in index d98c99d..aaed767 100644 --- a/wasp/boards/pinetime/watch.py.in +++ b/wasp/boards/pinetime/watch.py.in @@ -1,10 +1,16 @@ # SPDX-License-Identifier: LGPL-3.0-or-later # Copyright (C) 2020 Daniel Thompson +def nop(): + pass +schedule = nop +def _callback(obj): + schedule() + # Start measuring time (and feeding the watchdog) before *anything* else from machine import RTCounter from drivers.nrf_rtc import RTC -rtc = RTC(RTCounter(1, mode=RTCounter.PERIODIC)) +rtc = RTC(RTCounter(1, mode=RTCounter.PERIODIC, period=1, callback=_callback)) rtc.counter.start() import os @@ -83,7 +89,9 @@ try: i2c = I2C(1, scl='I2C_SCL', sda='I2C_SDA') accel = BMA421(i2c) hrs = HRS3300(i2c) - touch = CST816S(i2c, Pin('TP_INT', Pin.IN), Pin('TP_RST', Pin.OUT, value=0)) + touch = CST816S(i2c, + Pin('TP_INT', Pin.IN), Pin('TP_RST', Pin.OUT, value=0), + _callback) vibrator = Vibrator(Pin('MOTOR', Pin.OUT, value=0), active_low=True) # Release flash from deep power-down diff --git a/wasp/drivers/cst816s.py b/wasp/drivers/cst816s.py index 135c15f..2aeaf25 100644 --- a/wasp/drivers/cst816s.py +++ b/wasp/drivers/cst816s.py @@ -15,7 +15,7 @@ class CST816S: .. automethod:: __init__ """ - def __init__(self, bus, intr, rst): + def __init__(self, bus, intr, rst, schedule=None): """Specify the bus used by the touch controller. :param machine.I2C bus: I2C bus for the CST816S. @@ -23,6 +23,7 @@ class CST816S: self.i2c = bus self.tp_int = intr self.tp_rst = rst + self.schedule = schedule self.dbuf = bytearray(6) self.event = array.array('H', (0, 0, 0)) @@ -53,6 +54,9 @@ class CST816S: event[1] = ((dbuf[2] & 0xf) << 8) + dbuf[3] # x coord event[2] = ((dbuf[4] & 0xf) << 8) + dbuf[5] # y coord + if self.schedule: + self.schedule(self) + def get_event(self): """Receive a touch event. diff --git a/wasp/main.py b/wasp/main.py index 88fb87e..8680219 100644 --- a/wasp/main.py +++ b/wasp/main.py @@ -2,4 +2,4 @@ # Copyright (C) 2020 Daniel Thompson import wasp -wasp.system.run() +wasp.system.schedule() diff --git a/wasp/wasp.py b/wasp/wasp.py index 092ad29..a9f1a30 100644 --- a/wasp/wasp.py +++ b/wasp/wasp.py @@ -17,6 +17,7 @@ import gc import machine +import micropython import watch import widgets @@ -106,6 +107,8 @@ class Manager(): self._brightness = 2 self._button = PinHandler(watch.button) self._charging = True + self._scheduled = False + self._scheduling = False # TODO: Eventually these should move to main.py self.register(ClockApp(), True) @@ -242,7 +245,8 @@ class Manager(): """Return to a running state. """ watch.display.poweron() - self.app.wake() + if 'wake' in dir(self.app): + self.app.wake() watch.backlight.set(self._brightness) watch.touch.wake() @@ -326,6 +330,10 @@ class Manager(): normal execution context meaning any exceptions and other problems can be observed interactively via the console. """ + if self._scheduling: + print('Watch already running in the background') + return + if not self.app: self.switch(self.quick_ring[0]) @@ -353,8 +361,36 @@ class Manager(): # Currently there is no code to control how fast the system # ticks. In other words this code will break if we improve the - # power management... we are currently relying on no being able + # power management... we are currently relying on not being able # to stay in the low-power state for very long. machine.deepsleep() + def _work(self): + self._scheduled = False + try: + self._tick() + except Exception as e: + # Only print the exception if the watch provides a way to do so! + if 'print_exception' in dir(watch): + watch.print_exception(e) + self.switch(CrashApp(e)) + + def _schedule(self): + """Asynchronously schedule a system management cycle.""" + if not self._scheduled: + self._scheduled = True + micropython.schedule(Manager._work, self) + + def schedule(self, enable=True): + """Run the system manager synchronously.""" + if not self.app: + self.switch(self.quick_ring[0]) + + if enable: + watch.schedule = self._schedule + else: + watch.schedule = watch.nop + + self._scheduling = enable + system = Manager()