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>
This commit is contained in:
parent
11be7ca328
commit
ae5743529f
6 changed files with 57 additions and 8 deletions
|
@ -1 +1 @@
|
|||
Subproject commit d11200432c211fc9e413c74eace1308c1c5e9ff1
|
||||
Subproject commit df61f43d562ec33388bdb27b07fb6f0bbdbe8b8b
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
# Copyright (C) 2020 Daniel Thompson
|
||||
|
||||
import wasp
|
||||
wasp.system.run()
|
||||
wasp.system.schedule()
|
||||
|
|
40
wasp/wasp.py
40
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()
|
||||
|
|
Loading…
Reference in a new issue