summaryrefslogtreecommitdiff
path: root/wasp/apps
diff options
context:
space:
mode:
Diffstat (limited to 'wasp/apps')
-rw-r--r--wasp/apps/clock.py47
-rw-r--r--wasp/apps/flashlight.py35
-rw-r--r--wasp/apps/launcher.py80
-rw-r--r--wasp/apps/testapp.py173
4 files changed, 252 insertions, 83 deletions
diff --git a/wasp/apps/clock.py b/wasp/apps/clock.py
index f99091a..4236d9a 100644
--- a/wasp/apps/clock.py
+++ b/wasp/apps/clock.py
@@ -1,7 +1,10 @@
+# SPDX-License-Identifier: LGPL-3.0-or-later
+# Copyright (C) 2020 Daniel Thompson
+
+import wasp
+
+import icons
import fonts.clock as digits
-import watch
-import widgets
-import manager
DIGITS = (
digits.clock_0,
@@ -18,35 +21,22 @@ DIGITS = (
MONTH = 'JanFebMarAprMayJunJulAugSepOctNovDec'
-class ClockApp(object):
+class ClockApp():
"""Simple digital clock application.
Shows a time (as HH:MM) together with a battery meter and the date.
"""
+ NAME = 'Clock'
+ ICON = icons.clock
def __init__(self):
- self.meter = widgets.BatteryMeter()
-
- def handle_event(self, event_view):
- """Process events that the app is subscribed to."""
- if event_view[0] == manager.EVENT_TICK:
- self.update()
- else:
- # TODO: Raise an unexpected event exception
- pass
+ self.meter = wasp.widgets.BatteryMeter()
- def foreground(self, manager, effect=None):
+ def foreground(self):
"""Activate the application."""
self.on_screen = ( -1, -1, -1, -1, -1, -1 )
- self.draw(effect)
- manager.request_tick(1000)
-
- def tick(self, ticks):
- self.update()
-
- def background(self):
- """De-activate the application (without losing state)."""
- pass
+ self.draw()
+ wasp.system.request_tick(1000)
def sleep(self):
return True
@@ -54,9 +44,12 @@ class ClockApp(object):
def wake(self):
self.update()
- def draw(self, effect=None):
+ def tick(self, ticks):
+ self.update()
+
+ def draw(self):
"""Redraw the display from scratch."""
- draw = watch.drawable
+ draw = wasp.watch.drawable
draw.fill()
draw.rleblit(digits.clock_colon, pos=(2*48, 80), fg=0xb5b6)
@@ -70,14 +63,14 @@ class ClockApp(object):
The updates are a lazy as possible and rely on an prior call to
draw() to ensure the screen is suitably prepared.
"""
- now = watch.rtc.get_localtime()
+ now = wasp.watch.rtc.get_localtime()
if now[3] == self.on_screen[3] and now[4] == self.on_screen[4]:
if now[5] != self.on_screen[5]:
self.meter.update()
self.on_screen = now
return False
- draw = watch.drawable
+ draw = wasp.watch.drawable
draw.rleblit(DIGITS[now[4] % 10], pos=(4*48, 80))
draw.rleblit(DIGITS[now[4] // 10], pos=(3*48, 80), fg=0xbdb6)
draw.rleblit(DIGITS[now[3] % 10], pos=(1*48, 80))
diff --git a/wasp/apps/flashlight.py b/wasp/apps/flashlight.py
index f1f9418..c4702a0 100644
--- a/wasp/apps/flashlight.py
+++ b/wasp/apps/flashlight.py
@@ -1,32 +1,33 @@
-import watch
-import manager
+# SPDX-License-Identifier: LGPL-3.0-or-later
+# Copyright (C) 2020 Daniel Thompson
+
+import wasp
+
+import icons
class FlashlightApp(object):
"""Trivial flashlight application.
Shows a pure white screen with the backlight set to maximum.
"""
+ NAME = 'Torch'
+ ICON = icons.torch
- def __init__(self):
- self.backlight = None
-
- def foreground(self, manager, effect=None):
+ def foreground(self):
"""Activate the application."""
- self.on_screen = ( -1, -1, -1, -1, -1, -1 )
- self.draw(effect)
- manager.request_tick(1000)
+ self.draw()
+ wasp.system.request_tick(1000)
+
+ self._brightness = wasp.system.brightness
+ wasp.system.brightness = 3
def background(self):
"""De-activate the application (without losing state)."""
- pass
-
- def sleep(self):
- return False
+ wasp.system.brightness = self._brightness
def tick(self, ticks):
- pass
+ wasp.system.keep_awake()
- def draw(self, effect=None):
+ def draw(self):
"""Redraw the display from scratch."""
- display = watch.display
- display.fill(0xffff)
+ wasp.watch.display.fill(0xffff)
diff --git a/wasp/apps/launcher.py b/wasp/apps/launcher.py
new file mode 100644
index 0000000..274ea9c
--- /dev/null
+++ b/wasp/apps/launcher.py
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: LGPL-3.0-or-later
+# Copyright (C) 2020 Daniel Thompson
+
+import wasp
+import icons
+
+class LauncherApp():
+ """An application launcher application.
+ """
+ NAME = 'Launcher'
+ ICON = icons.app
+
+ def foreground(self):
+ """Activate the application."""
+ self._page = 0
+ self._draw()
+ wasp.system.request_event(wasp.EventMask.TOUCH |
+ wasp.EventMask.SWIPE_UPDOWN)
+
+ def swipe(self, event):
+ i = self._page
+ n = self._num_pages
+ if event[0] == wasp.EventType.UP:
+ i += 1
+ if i >= n:
+ i -= 1
+ wasp.watch.vibrator.pulse()
+ return
+ else:
+ i -= 1
+ if i < 0:
+ wasp.system.switch(wasp.system.applications[0])
+ return
+
+ self._page = i
+ wasp.watch.display.mute(True)
+ self._draw()
+ wasp.watch.display.mute(False)
+
+ def touch(self, event):
+ page = self._get_page(self._page)
+ x = event[1]
+ y = event[2]
+ app = page[2 * (y // 120) + (x // 120)]
+ if app:
+ wasp.system.switch(app)
+ else:
+ wasp.watch.vibrator.pulse()
+
+ @property
+ def _num_pages(self):
+ """Work out what the highest possible pages it."""
+ num_apps = len(wasp.system.applications)
+ return (num_apps + 3) // 4
+
+ def _get_page(self, i):
+ apps = wasp.system.applications
+ page = apps[4*i: 4*(i+1)]
+ while len(page) < 4:
+ page.append(None)
+ return page
+
+ def _draw(self):
+ """Redraw the display from scratch."""
+ def draw_app(app, x, y):
+ if not app:
+ return
+ draw.set_color(0xffff)
+ draw.rleblit(app.ICON, (x+13, y+12))
+ draw.set_color(0xbdb6)
+ draw.string(app.NAME, x, y+120-30, 120)
+
+ draw = wasp.watch.drawable
+ page = self._get_page(self._page)
+
+ draw.fill()
+ draw_app(page[0], 0, 0)
+ draw_app(page[1], 120, 0)
+ draw_app(page[2], 0, 120)
+ draw_app(page[3], 120, 120)
diff --git a/wasp/apps/testapp.py b/wasp/apps/testapp.py
index 9f512f1..eece822 100644
--- a/wasp/apps/testapp.py
+++ b/wasp/apps/testapp.py
@@ -1,62 +1,157 @@
-import watch
-import widgets
-import manager
+# SPDX-License-Identifier: LGPL-3.0-or-later
+# Copyright (C) 2020 Daniel Thompson
+
import machine
+import wasp
+import icons
class TestApp():
"""Simple test application.
"""
+ NAME = 'Self Test'
+ ICON = icons.app
+
+ # 2-bit RLE, generated from res/app_icon.png, 457 bytes
+ RLE_2BIT = (
+ 96, 64,
+ b'\x1e@md<d<d;f?X\xec2\xf0/'
+ b'\xf2-\xf4,\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,'
+ b'\xc3.\xc3,\xc3.\xc3,\xc3\x0c\x80\xfc\x83\x10\xc0]'
+ b'\xc3\x0c@\xffC,C\n\x87\x0c\xc7\nC,C\t'
+ b'\x83\x02\x84\n\xc4\x02\xc3\tC,C\x08\x82\x07\x82\x08'
+ b'\xc2\x07\xc2\x08C,C\x07\x82\t\x82\x06\xc2\t\xc2\x07'
+ b'C,C\x06\x82\x0b\x82\x04\xc2\x0b\xc2\x06C,C\x06'
+ b'\x82\x0b\x82\x04\xc2\x0b\xc2\x06C,C\x05\x82\x0c\x82\x04'
+ b'\xc2\x0c\xc2\x05C,C\x05\x82\x0c\x82\x04\xc2\x0c\xc2\x05'
+ b'C,C\x05\x83\x0b\x82\x04\xc2\x0b\xc3\x05C,C\x06'
+ b'\x82\x0b\x82\x04\xc2\x0b\xc2\x06C,C\x06\x82\x0b\x82\x04'
+ b'\xc2\x0b\xc1\x07C,C\x07\x82\n\x82\x04\xc2\n\xc2\x07'
+ b'C+D\x08\x82\t\x82\x04\xc2\t\xc2\x08C*E\t'
+ b'\x8c\x04\xcc\tC*E\n\x8b\x04\xcb\nC*E.'
+ b'C*E.C*E.C*E.C*E\n'
+ b'\x80\xe9\x8b\x04\xc0o\xcb\nC+D\t\x8c\x04\xcc\t'
+ b'C,C\x08\x82\t\x82\x04\xc2\t\xc2\x08C,C\x07'
+ b'\x82\n\x82\x04\xc2\n\xc2\x07C,C\x06\x82\x0b\x82\x04'
+ b'\xc2\x0b\xc1\x07C,C\x06\x82\x0b\x82\x04\xc2\x0b\xc2\x06'
+ b'C,C\x05\x83\x0b\x82\x04\xc2\x0b\xc3\x05C,C\x05'
+ b'\x82\x0c\x82\x04\xc2\x0c\xc2\x05C,C\x05\x82\x0c\x82\x04'
+ b'\xc2\x0c\xc2\x05C,C\x06\x82\x0b\x82\x04\xc2\x0b\xc2\x06'
+ b'C,C\x06\x82\x0b\x82\x04\xc2\x0b\xc2\x06C,C\x07'
+ b'\x82\t\x82\x06\xc2\t\xc2\x07C,C\x08\x82\x07\x82\x08'
+ b'\xc2\x07\xc2\x08C,C\t\x83\x02\x84\n\xc4\x02\xc3\t'
+ b'C,C\n\x86\x0e\xc6\nC,C\x0c\x83\x10\xc3\x0c'
+ b'C,C.C,C.C,C.C,C.'
+ b'C,C.C,t-r/p2l?X@'
+ b'mf;d<d<d\x1e'
+ )
def __init__(self):
- self.tests = ('Touch', 'String')
+ self.tests = ('Touch', 'String', 'Button', 'Crash', '1-bit RLE', '2-bit RLE')
self.test = self.tests[0]
+ self.scroll = wasp.widgets.ScrollIndicator()
- def foreground(self, system, effect=None):
+ def foreground(self):
"""Activate the application."""
self.on_screen = ( -1, -1, -1, -1, -1, -1 )
- self.draw(effect)
- system.request_event(manager.EVENT_TOUCH | manager.EVENT_SWIPE_LEFTRIGHT)
-
- def background(self):
- """De-activate the application (without losing state)."""
- pass
+ self.draw()
+ wasp.system.request_event(wasp.EventMask.TOUCH |
+ wasp.EventMask.SWIPE_UPDOWN |
+ wasp.EventMask.BUTTON)
- def sleep(self):
- return False
+ def press(self, button, state):
+ draw = wasp.watch.drawable
+ if self.test == 'Touch':
+ draw.string('Button', 0, 108, width=240)
+ if self.test == 'String':
+ self.benchmark_string()
+ elif self.test == 'Button':
+ draw.string('{}: {}'.format(button, state), 0, 108, width=240)
+ elif self.test == 'Crash':
+ self.crash()
def swipe(self, event):
tests = self.tests
- i = tests.index(self.test) + 1
- if i >= len(tests):
- i = 0
+ i = tests.index(self.test)
+
+ if event[0] == wasp.EventType.UP:
+ i += 1
+ if i >= len(tests):
+ i = 0
+ else:
+ i -= 1
+ if i < 0:
+ i = len(tests) - 1
self.test = tests[i]
self.draw()
def touch(self, event):
- draw = watch.drawable
if self.test == 'Touch':
- draw.string('({}, {})'.format(event[1], event[2]),
- 0, 108, width=240)
+ wasp.watch.drawable.string('({}, {})'.format(
+ event[1], event[2]), 0, 108, width=240)
elif self.test == 'String':
- draw.fill(0, 0, 30, 240, 240-30)
- t = machine.Timer(id=1, period=8000000)
- t.start()
- draw.string("The quick brown", 12, 24+24)
- draw.string("fox jumped over", 12, 24+48)
- draw.string("the lazy dog.", 12, 24+72)
- draw.string("0123456789", 12, 24+120)
- draw.string('!"£$%^&*()', 12, 24+144)
- elapsed = t.time()
- t.stop()
- del t
- draw.string('{}s'.format(elapsed / 1000000), 12, 24+192)
-
- return True
-
- def draw(self, effect=None):
+ self.benchmark_string()
+ elif self.test == '1-bit RLE':
+ self.benchmark_rle_1bit()
+ elif self.test == '2-bit RLE':
+ self.benchmark_rle_2bit()
+
+ def benchmark_rle_1bit(self):
+ draw = wasp.watch.drawable
+ draw.fill(0, 0, 30, 240, 240-30)
+ self.scroll.draw()
+ t = machine.Timer(id=1, period=8000000)
+ t.start()
+ for i in range(0, 128, 16):
+ draw.rleblit(self.ICON, (i, 30 + i))
+ elapsed = t.time()
+ t.stop()
+ del t
+ draw.string('{}s'.format(elapsed / 1000000), 12, 24+192)
+
+ def benchmark_rle_2bit(self):
+ draw = wasp.watch.drawable
+ draw.fill(0, 0, 30, 240, 240-30)
+ self.scroll.draw()
+ t = machine.Timer(id=1, period=8000000)
+ t.start()
+ for i in range(0, 128, 16):
+ draw.rle2bit(self.RLE_2BIT, i, 30 + i)
+ elapsed = t.time()
+ t.stop()
+ del t
+ draw.string('{}s'.format(elapsed / 1000000), 12, 24+192)
+
+ def benchmark_string(self):
+ draw = wasp.watch.drawable
+ draw.fill(0, 0, 30, 240, 240-30)
+ self.scroll.draw()
+ t = machine.Timer(id=1, period=8000000)
+ t.start()
+ draw.string("The quick brown", 12, 24+24)
+ draw.string("fox jumped over", 12, 24+48)
+ draw.string("the lazy dog.", 12, 24+72)
+ draw.string("0123456789", 12, 24+120)
+ draw.string('!"£$%^&*()', 12, 24+144)
+ elapsed = t.time()
+ t.stop()
+ del t
+ draw.string('{}s'.format(elapsed / 1000000), 12, 24+192)
+
+ def draw(self):
"""Redraw the display from scratch."""
- watch.display.mute(True)
- watch.drawable.fill()
- watch.drawable.string('{} test'.format(self.test),
+ wasp.watch.display.mute(True)
+ draw = wasp.watch.drawable
+ draw.fill()
+ draw.string('{} test'.format(self.test),
0, 6, width=240)
- watch.display.mute(False)
+ self.scroll.draw()
+
+ if self.test == 'Crash':
+ draw.string("Press button to", 12, 24+24)
+ draw.string("throw exception.", 12, 24+48)
+ elif self.test == '1-bit RLE':
+ draw.rleblit(self.ICON, (120-48, 120-32))
+ elif self.test == '2-bit RLE':
+ draw.rle2bit(self.RLE_2BIT, 120-48, 120-32)
+
+ wasp.watch.display.mute(False)