1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2021 Francesco Gazzetta
"""Morse translator and notepad
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This app is a simple morse translator that also doubles as a notepad.
Swipe up for a line, swipe down for a dot, tap for end letter, double tap for
end word.
Up to 7 lines of translation will be displayed on a 240x240 screen, and old
lines will be deleted.
There is a preview of the next letter at the bottom of the screen.
.. figure:: res/MorseApp.png
:width: 179
"""
import wasp
import icons
import fonts
from math import floor
from micropython import const
_WIDTH = const(240)
_HEIGHT = const(240)
# No easy way to make this depend on _WIDTH
_MAXINPUT = const(16)
# These two need to match
_FONTH = const(24)
_FONT = fonts.sans24
_LINEH = int(_FONTH * 1.25)
_MAXLINES = floor(_HEIGHT / _LINEH) - 1 # the "-1" is the input line
_code = {
"" : " ",
".-" : "A",
"-..." : "B",
"-.-." : "C",
"-.." : "D",
"." : "E",
"..-." : "F",
"--." : "G",
"...." : "H",
".." : "I",
".---" : "J",
"-.-" : "K",
".-.." : "L",
"--" : "M",
"-." : "N",
"---" : "O",
".--." : "P",
"--.-" : "Q",
".-." : "R",
"..." : "S",
"-" : "T",
"..-" : "U",
"...-" : "V",
".--" : "W",
"-..-" : "X",
"-.--" : "Y",
"--.." : "Z",
".----": "1",
"..---": "2",
"...--": "3",
"....-": "4",
".....": "5",
"-....": "6",
"--...": "7",
"---..": "8",
"----.": "9",
"-----": "0",
}
class MorseApp():
NAME = 'Morse'
# 2-bit RLE, 96x64, generated from res/morse_icon.png, 143 bytes
ICON = (
b'\x02'
b'`@'
b'?\xff\xff\xff\xff\x13\xc4?\x1c\xc6?\x1b\xc6?\x1b\xc6'
b'?\x1a\xc8?\x19\xc8?\x18\xca?\x17\xc4\x02\xc4?\x17'
b'\xc4\x02\xc4?\x16\xc5\x02\xc5?\x15\xc4\x04\xc4?\x15\xc4'
b'\x04\xc4?\x14\xc4\x06\xc4?\x13\xc4\x06\xc4?\x12\xc5\x06'
b'\xc5?\x11\xc4\x08\xc4?\x11\xd0?\x10\xd2?\x0f\xd2?'
b'\x0e\xc5\n\xc4?\x0e\xc4\x0c\xc4?\r\xc4\x0c\xc4?\x0c'
b'\xc5\x0c\xc5?\x0b\xc4\x0e\xc4?\x0b\xc4\x0e\xc4?\n\xc4'
b'\x10\xc4?\xff\xff\xff\xff\x83\xc4\x0e\xda4\xc4\x0e\xda4'
b'\xc4\x0e\xda4\xc4\x0e\xda?\xff\xff\xff\xfe'
)
def __init__(self):
self.letter = ""
self.text = [""]
pass
def foreground(self):
self._draw()
wasp.system.request_event(wasp.EventMask.TOUCH |
wasp.EventMask.SWIPE_UPDOWN)
def swipe(self, event):
if len(self.letter) < _MAXINPUT:
self.letter += "-" if event[0] == wasp.EventType.UP else "."
self._update()
def touch(self, event):
addition = _code[self.letter] if self.letter in _code else "/{}/".format(self.letter)
self.letter = ""
merged = self.text[-1] + addition
# Check if the new text overflows the screen and add a new line if that's the case
split = wasp.watch.drawable.wrap(merged, _WIDTH)
if len(split) > 2:
self.text.append(self.text[-1][split[1]:split[2]] + addition)
self.text[-2] = self.text[-2][split[0]:split[1]]
if len(self.text) > _MAXLINES:
self.text.pop(0)
# Ideally a full refresh should be done only when we exceed
# _MAXLINES, but this should be fast enough
self._draw()
else:
self.text[-1] = merged
self._update()
def _draw(self):
"""Draw the display from scratch"""
draw = wasp.watch.drawable
draw.fill()
i = 0
for line in self.text:
draw.string(line, 0, _LINEH * i)
i += 1
self._update()
def _update(self):
"""Update the dynamic parts of the application display, specifically the
input line and last line of the text.
The full text area is updated in _draw() instead."""
draw = wasp.watch.drawable
draw.string(self.text[-1], 0, _LINEH*(len(self.text)-1))
guess = _code[self.letter] if self.letter in _code else "?"
draw.string("{} {}".format(self.letter, guess), 0, _HEIGHT - _FONTH, width=_WIDTH)
|