From 5b74c45e58eedddf3432b595822989afba8bf3a4 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Thu, 31 Dec 2020 17:18:13 +0100 Subject: [PATCH] apps: timer: Add a countdown timer application Signed-off-by: Wolfgang Ginolas [daniel@redfelineninja.org.uk: squashed into a single commit, rebase to latest master, integrate with the Software application and rename the screenshots to match the application name] Signed-off-by: Daniel Thompson --- README.rst | 6 +- docs/apps.rst | 2 + res/StopclockApp.png | Bin 0 -> 7386 bytes res/TimerApp.png | Bin 6904 -> 15666 bytes res/timer_icon.png | Bin 0 -> 1066 bytes wasp/apps/software.py | 1 + wasp/apps/stopwatch.py | 5 +- wasp/apps/timer.py | 173 ++++++++++++++++++++++++++++++++ wasp/boards/manifest_240x240.py | 1 + 9 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 res/StopclockApp.png create mode 100644 res/timer_icon.png create mode 100644 wasp/apps/timer.py diff --git a/README.rst b/README.rst index 8985e40..5ca32a9 100644 --- a/README.rst +++ b/README.rst @@ -137,7 +137,7 @@ simulator (the "blank" screen is the torch application): :alt: Heart rate application running on the wasp-os simulator :width: 179 -.. image:: res/TimerApp.png +.. image:: res/StopclockApp.png :alt: Stop watch application running on the wasp-os simulator :width: 179 @@ -192,3 +192,7 @@ using one of the techniques is the Application Writer's guide. .. image:: res/SnakeApp.png :alt: Snake Game running in the wasp-os simulator :width: 179 + +.. image:: res/TimerApp.png + :alt: Countdown timer application running in the wasp-os simulator + :width: 179 diff --git a/docs/apps.rst b/docs/apps.rst index ae9fb15..5cadd94 100644 --- a/docs/apps.rst +++ b/docs/apps.rst @@ -40,3 +40,5 @@ Integration .. automodule:: apps.alarm .. automodule:: apps.musicplayer + +.. automodule:: apps.timer diff --git a/res/StopclockApp.png b/res/StopclockApp.png new file mode 100644 index 0000000000000000000000000000000000000000..3c14c741d7761d9884d7406dc39d7ea8dfba6336 GIT binary patch literal 7386 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 F{{bG%){g)H literal 6904 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 literal 0 HcmV?d00001 diff --git a/wasp/apps/software.py b/wasp/apps/software.py index a39cce0..b8bea2c 100644 --- a/wasp/apps/software.py +++ b/wasp/apps/software.py @@ -22,6 +22,7 @@ class SoftwareApp(): ('snake', wasp.widgets.Checkbox(0, 40, 'Snake Game')), ('flashlight', wasp.widgets.Checkbox(0, 80, 'Torch')), ('testapp', wasp.widgets.Checkbox(0, 120, 'Test')), + ('timer', wasp.widgets.Checkbox(0, 160, 'Timer')), ) self.si = wasp.widgets.ScrollIndicator() self.page = 0 diff --git a/wasp/apps/stopwatch.py b/wasp/apps/stopwatch.py index 0d572af..f46baa0 100644 --- a/wasp/apps/stopwatch.py +++ b/wasp/apps/stopwatch.py @@ -8,12 +8,13 @@ import fonts class StopwatchApp(): """Stopwatch application. - .. figure:: res/TimerApp.png + .. figure:: res/StopclockApp.png :width: 179 Screenshot of the stopwatch application """ - NAME = 'Timer' + # Stopwatch requires too many pixels to fit into the launcher + NAME = 'Stopclock' ICON = icons.app def __init__(self): diff --git a/wasp/apps/timer.py b/wasp/apps/timer.py new file mode 100644 index 0000000..f1543f8 --- /dev/null +++ b/wasp/apps/timer.py @@ -0,0 +1,173 @@ +# SPDX-License-Identifier: LGPL-3.0-or-later +# Copyright (C) 2020 Wolfgang Ginolas +"""Timer Application +~~~~~~~~~~~~~~~~~~~~ + +An application to set a vibration in a specified amount of time. Like a kitchen timer. + + .. figure:: res/TimerApp.png + :width: 179 + + Screenshot of the Timer Application + +""" + +import wasp +import fonts +import time +import widgets +import math +from micropython import const + +# 2-bit RLE, generated from res/timer_icon.png, 345 bytes +icon = ( + b'\x02' + b'`@' + b'?\xff\r@\xb4I?\x14Q?\rW?\x08[?' + b'\x04_?\x00c= _BUTTON_Y: + self._start() + + + def _start(self): + self.state = _RUNNING + now = wasp.watch.rtc.time() + self.current_alarm = now + self.minutes.value * 60 + self.seconds.value + wasp.system.set_alarm(self.current_alarm, self._alert) + self._draw() + + def _stop(self): + self.state = _STOPPED + wasp.system.cancel_alarm(self.current_alarm, self._alert) + self._draw() + + def _draw(self): + """Draw the display from scratch.""" + draw = wasp.watch.drawable + draw.fill() + sbar = wasp.system.bar + sbar.clock = True + sbar.draw() + + if self.state == _RINGING: + draw.set_font(fonts.sans24) + draw.string(self.NAME, 0, 150, width=240) + draw.blit(icon, 73, 50) + elif self.state == _RUNNING: + self._draw_stop(104, _BUTTON_Y) + draw.string(':', 110, 120-14, width=20) + self._update() + else: # _STOPPED + draw.set_font(fonts.sans28) + draw.string(':', 110, 120-14, width=20) + + self.minutes.draw() + self.seconds.draw() + + self._draw_play(114, _BUTTON_Y) + + def _update(self): + wasp.system.bar.update() + draw = wasp.watch.drawable + if self.state == _RUNNING: + now = wasp.watch.rtc.time() + s = self.current_alarm - now + if s<0: + s = 0 + m = str(math.floor(s // 60)) + s = str(math.floor(s) % 60) + if len(m) < 2: + m = '0' + m + if len(s) < 2: + s = '0' + s + draw.set_font(fonts.sans28) + draw.string(m, 50, 120-14, width=60) + draw.string(s, 130, 120-14, width=60) + + def _draw_play(self, x, y): + draw = wasp.watch.drawable + for i in range(0,20): + draw.fill(0xffff, x+i, y+i, 1, 40 - 2*i) + + def _draw_stop(self, x, y): + wasp.watch.drawable.fill(0xffff, x, y, 40, 40) + + def _alert(self): + self.state = _RINGING + wasp.system.wake() + wasp.system.switch(self) diff --git a/wasp/boards/manifest_240x240.py b/wasp/boards/manifest_240x240.py index 4d91566..ed3a692 100644 --- a/wasp/boards/manifest_240x240.py +++ b/wasp/boards/manifest_240x240.py @@ -21,6 +21,7 @@ manifest = ( 'apps/stopwatch.py', 'apps/snake.py', 'apps/testapp.py', + 'apps/timer.py', 'fonts/__init__.py', 'fonts/clock.py', 'fonts/sans24.py',