diff options
Diffstat (limited to 'wasp/apps')
| -rw-r--r-- | wasp/apps/clock.py | 47 | ||||
| -rw-r--r-- | wasp/apps/flashlight.py | 35 | ||||
| -rw-r--r-- | wasp/apps/launcher.py | 80 | ||||
| -rw-r--r-- | wasp/apps/testapp.py | 173 |
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) |
