summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfgang Ginolas <wolfgang.ginolas@gwif.eu>2020-12-31 16:18:13 (GMT)
committerDaniel Thompson <daniel@redfelineninja.org.uk>2021-01-10 16:02:35 (GMT)
commit5b74c45e58eedddf3432b595822989afba8bf3a4 (patch)
treef524373a333b23210273f57a2acfdca4bba09fa5
parent4e9a576a2df3476a19522df177f845fade7b1fa6 (diff)
apps: timer: Add a countdown timer application
Signed-off-by: Wolfgang Ginolas <wolfgang.ginolas@gwif.eu> [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 <daniel@redfelineninja.org.uk>
-rw-r--r--README.rst6
-rw-r--r--docs/apps.rst2
-rw-r--r--res/StopclockApp.pngbin0 -> 7386 bytes
-rw-r--r--res/TimerApp.pngbin6904 -> 15666 bytes
-rw-r--r--res/timer_icon.pngbin0 -> 1066 bytes
-rw-r--r--wasp/apps/software.py1
-rw-r--r--wasp/apps/stopwatch.py5
-rw-r--r--wasp/apps/timer.py173
-rw-r--r--wasp/boards/manifest_240x240.py1
9 files changed, 185 insertions, 3 deletions
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 0000000..3c14c74
--- /dev/null
+++ b/res/StopclockApp.png
Binary files differ
diff --git a/res/TimerApp.png b/res/TimerApp.png
index eaa91de..8edb17e 100644
--- a/res/TimerApp.png
+++ b/res/TimerApp.png
Binary files differ
diff --git a/res/timer_icon.png b/res/timer_icon.png
new file mode 100644
index 0000000..6493f8d
--- /dev/null
+++ b/res/timer_icon.png
Binary files differ
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<Q\x80\xd0\x83Q:L\x87\x01\x87'
+ b'L8K\x89\x01\x89K6J\x8b\x01\x8bJ4I\x8d'
+ b'\x01\x8dI2I\x9dI0I\x83\x01\x97\x01\x83I.'
+ b'H\x86\x01\x95\x01\x86H-H\xa3H,H\x92\x01\x92'
+ b'H+G\x92\x03\x92G*G\x92\x05\x92G)G\x92'
+ b"\x05\x92G(G\x82\x01\x8f\x07\x8f\x01\x82G'G\x83"
+ b"\x01\x8e\x07\x8e\x01\x83G'F\x93\x07\x93F&G\x93"
+ b'\x07\x93G%F\x94\x07\x94F%F\x94\x07\x94F%'
+ b'F\x94\x07\x94F$G\x94\x07\x94G#G\x94\x07\x94'
+ b'G#G\x94\x07\x94G#F\x95\x07\x95F#F\x81'
+ b'\x04\x90\x07\x90\x04\x81F#F\x95\x07\x95F#G\x94'
+ b'\x07\x94G#G\x94\x07\x94G#G\x94\x07\x94G$'
+ b'F\x94\x07\x94F%F\x94\x07\x94F%F\x94\x07\x94'
+ b"F%G\x93\x07\x93G%G\x93\x07\x93F'G\x83"
+ b"\x01\x8e\x07\x8e\x01\x83G'G\x82\x01\x8f\x07\x8f\x01\x82"
+ b'G(G\x92\x05\x92G)G\x93\x03\x93G*G\xa7'
+ b'G+H\xa5H,G\xa5G-H\x86\x01\x9cH.'
+ b'H\x84\x01\x96\x01\x85H0I\x9a\x01\x82I1J\x8d'
+ b'\x01\x8dJ2K\x8b\x01\x8bK4K\x8a\x01\x89L5'
+ b'N\x87\x01\x87N5S\x85S5k5k5k5'
+ b'k5k5k\x1b'
+)
+
+_STOPPED = const(0)
+_RUNNING = const(1)
+_RINGING = const(2)
+
+_BUTTON_Y = const(200)
+
+class TimerApp():
+ """Allows the user to set a vibration alarm.
+ """
+ NAME = 'Timer'
+ ICON = icon
+
+ def __init__(self):
+ """Initialize the application."""
+ self.minutes = widgets.Spinner(50, 60, 0, 99, 2)
+ self.seconds = widgets.Spinner(130, 60, 0, 60, 2)
+ self.current_alarm = None
+
+ self.minutes.value = 10
+ self.state = _STOPPED
+
+ def foreground(self):
+ """Activate the application."""
+ self._draw()
+ wasp.system.request_event(wasp.EventMask.TOUCH)
+ wasp.system.request_tick(1000)
+
+ def background(self):
+ """De-activate the application."""
+ if self.state == _RINGING:
+ self.state = _STOPPED
+
+ def tick(self, ticks):
+ """Notify the application that its periodic tick is due."""
+ if self.state == _RINGING:
+ wasp.watch.vibrator.pulse(duty=50, ms=500)
+ wasp.system.keep_awake()
+ self._update()
+
+ def touch(self, event):
+ """Notify the application of a touchscreen touch event."""
+ if self.state == _RINGING:
+ mute = wasp.watch.display.mute
+ mute(True)
+ self._stop()
+ mute(False)
+ elif self.state == _RUNNING:
+ self._stop()
+ else: # _STOPPED
+ if self.minutes.touch(event) or self.seconds.touch(event):
+ pass
+ else:
+ y = event[2]
+ if y >= _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',