summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Thompson <daniel@redfelineninja.org.uk>2020-06-30 22:04:01 (GMT)
committerDaniel Thompson <daniel@redfelineninja.org.uk>2020-06-30 22:04:01 (GMT)
commitae5743529f82d398876456b7e175defb19a6ccfc (patch)
treeabaebb87754a952a15d7b062d36bfd9b668794e3
parent11be7ca3280134cf4e565198f87c316179cf2dc9 (diff)
wasp: Switch to scheduling from interrupt
This has two useful properties. Firstly it means the watch will be maintained in the background, allowing the REPL to be used for notifications and other updates. Secondly it will save a little bit of power by reducing the work needed to handle spurious wake ups. Signed-off-by: Daniel Thompson <daniel@redfelineninja.org.uk>
m---------micropython0
-rwxr-xr-xtools/wasptool3
-rw-r--r--wasp/boards/pinetime/watch.py.in12
-rw-r--r--wasp/drivers/cst816s.py6
-rw-r--r--wasp/main.py2
-rw-r--r--wasp/wasp.py40
6 files changed, 56 insertions, 7 deletions
diff --git a/micropython b/micropython
-Subproject d11200432c211fc9e413c74eace1308c1c5e9ff
+Subproject df61f43d562ec33388bdb27b07fb6f0bbdbe8b8
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()