Advanced alarm app

Features:
* Multiple alarms (up to 4)
* Day of the week support
* One time alarms
* Snooze

Changes to wasp-os for app support:
* Added + and - to the 28pt and 36pt fonts
* Checkboxes now require a click on the body of the checkbox if there is no label
* Added a Toggle Button class that extends Button and stores a state like checkbox

Signed-off-by: Adam Blair <adampblair@protonmail.com>
This commit is contained in:
Adam Blair 2021-06-23 15:31:42 -06:00 committed by Daniel Thompson
parent 0831f79a10
commit e09b951017
5 changed files with 513 additions and 216 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@ -1,6 +1,7 @@
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020 Daniel Thompson
# Copyright (C) 2020 Joris Warmbier
# Copyright (C) 2021 Adam Blair
"""Alarm Application
~~~~~~~~~~~~~~~~~~~~
@ -12,11 +13,12 @@ An application to set a vibration alarm. All settings can be accessed from the W
Screenshot of the Alarm Application
"""
import wasp
import fonts
import time
import widgets
import array
from micropython import const
# 2-bit RLE, generated from res/alarm_icon.png, 390 bytes
icon = (
@ -49,7 +51,29 @@ icon = (
b'\x11\x83\x17'
)
class AlarmApp():
# Enabled masks
_MONDAY = const(0x01)
_TUESDAY = const(0x02)
_WEDNESDAY = const(0x04)
_THURSDAY = const(0x08)
_FRIDAY = const(0x10)
_SATURDAY = const(0x20)
_SUNDAY = const(0x40)
_WEEKDAYS = const(0x1F)
_WEEKENDS = const(0x60)
_EVERY_DAY = const(0x7F)
_IS_ACTIVE = const(0x80)
# Alarm data indices
_HOUR_IDX = const(0)
_MIN_IDX = const(1)
_ENABLED_IDX = const(2)
# Pages
_HOME_PAGE = const(-1)
_RINGING_PAGE = const(-2)
class AlarmApp:
"""Allows the user to set a vibration alarm.
"""
NAME = 'Alarm'
@ -57,83 +81,296 @@ class AlarmApp():
def __init__(self):
"""Initialize the application."""
self.active = widgets.Checkbox(104, 200)
self.hours = widgets.Spinner(50, 60, 0, 23, 2)
self.minutes = widgets.Spinner(130, 60, 0, 59, 2)
self.hours.value = 7
self.ringing = False
self.page = _HOME_PAGE
self.alarms = (bytearray(3), bytearray(3), bytearray(3), bytearray(3))
self.pending_alarms = array.array('d', [0.0, 0.0, 0.0, 0.0])
# Set a nice default
self.num_alarms = 1
for alarm in self.alarms:
alarm[_HOUR_IDX] = 8
alarm[_MIN_IDX] = 0
alarm[_ENABLED_IDX] = 0
self.alarms[0][_ENABLED_IDX] = _WEEKDAYS
def foreground(self):
"""Activate the application."""
self.del_alarm_btn = widgets.Button(170, 204, 70, 35, 'DEL')
self.hours_wid = widgets.Spinner(50, 30, 0, 23, 2)
self.min_wid = widgets.Spinner(130, 30, 0, 59, 2)
self.day_btns = (widgets.ToggleButton(10, 145, 40, 35, 'Mo'),
widgets.ToggleButton(55, 145, 40, 35, 'Tu'),
widgets.ToggleButton(100, 145, 40, 35, 'We'),
widgets.ToggleButton(145, 145, 40, 35, 'Th'),
widgets.ToggleButton(190, 145, 40, 35, 'Fr'),
widgets.ToggleButton(10, 185, 40, 35, 'Sa'),
widgets.ToggleButton(55, 185, 40, 35, 'Su'))
self.alarm_checks = (widgets.Checkbox(200, 57), widgets.Checkbox(200, 102),
widgets.Checkbox(200, 147), widgets.Checkbox(200, 192))
self._deactivate_pending_alarms()
self._draw()
wasp.system.request_event(wasp.EventMask.TOUCH)
wasp.system.request_event(wasp.EventMask.TOUCH | wasp.EventMask.SWIPE_LEFTRIGHT | wasp.EventMask.BUTTON)
wasp.system.request_tick(1000)
if self.active.state:
wasp.system.cancel_alarm(self.current_alarm, self._alert)
def background(self):
"""De-activate the application."""
if self.active.state:
self._set_current_alarm()
wasp.system.set_alarm(self.current_alarm, self._alert)
if self.ringing:
self.ringing = False
if self.page > _HOME_PAGE:
self._save_alarm()
self.page = _HOME_PAGE
del self.del_alarm_btn
del self.hours_wid
del self.min_wid
del self.alarm_checks
del self.day_btns
self._set_pending_alarms()
def tick(self, ticks):
"""Notify the application that its periodic tick is due."""
if self.ringing:
if self.page == _RINGING_PAGE:
wasp.watch.vibrator.pulse(duty=50, ms=500)
wasp.system.keep_awake()
else:
wasp.system.bar.update()
def press(self, button, state):
""""Notify the application of a button press event."""
if self.page == _RINGING_PAGE:
self._snooze()
wasp.system.navigate(wasp.EventType.HOME)
def swipe(self, event):
""""Notify the application of a swipe event."""
if self.page == _RINGING_PAGE:
self._silence_alarm()
elif self.page > _HOME_PAGE:
self._save_alarm()
self._draw()
else:
wasp.system.navigate(event[0])
def touch(self, event):
"""Notify the application of a touchscreen touch event."""
if self.ringing:
mute = wasp.watch.display.mute
self.ringing = False
mute(True)
self._draw()
mute(False)
elif self.hours.touch(event) or self.minutes.touch(event) or \
self.active.touch(event):
pass
if self.page == _RINGING_PAGE:
self._silence_alarm()
elif self.page > _HOME_PAGE:
if self.hours_wid.touch(event) or self.min_wid.touch(event):
return
for day_btn in self.day_btns:
if day_btn.touch(event):
return
if self.del_alarm_btn.touch(event):
self._remove_alarm(self.page)
elif self.page == _HOME_PAGE:
for index, checkbox in enumerate(self.alarm_checks):
if checkbox.touch(event):
if checkbox.state:
self.alarms[index][_ENABLED_IDX] |= _IS_ACTIVE
else:
self.alarms[index][_ENABLED_IDX] &= ~_IS_ACTIVE
self._draw(index)
return
for index, alarm in enumerate(self.alarms):
# Open edit page for clicked alarms
if index < self.num_alarms and event[1] < 190 \
and 60 + (index * 45) < event[2] < 60 + ((index + 1) * 45):
self.page = index
self._draw()
return
# Add new alarm if plus clicked
elif index == self.num_alarms and 60 + (index * 45) < event[2]:
self.num_alarms += 1
self._draw(index)
return
def _draw(self):
"""Draw the display from scratch."""
draw = wasp.watch.drawable
if not self.ringing:
draw.fill()
def _remove_alarm(self, alarm_index):
# Shift alarm indices
for index in range(alarm_index, 3):
self.alarms[index][_HOUR_IDX] = self.alarms[index + 1][_HOUR_IDX]
self.alarms[index][_MIN_IDX] = self.alarms[index + 1][_MIN_IDX]
self.alarms[index][_ENABLED_IDX] = self.alarms[index + 1][_ENABLED_IDX]
self.pending_alarms[index] = self.pending_alarms[index + 1]
sbar = wasp.system.bar
sbar.clock = True
sbar.draw()
# Set last alarm to default
self.alarms[3][_HOUR_IDX] = 8
self.alarms[3][_MIN_IDX] = 0
self.alarms[3][_ENABLED_IDX] = 0
draw.set_font(fonts.sans28)
draw.string(':', 110, 120-14, width=20)
self.page = _HOME_PAGE
self.num_alarms -= 1
self._draw()
self.active.draw()
self.hours.draw()
self.minutes.draw()
def _save_alarm(self):
alarm = self.alarms[self.page]
alarm[_HOUR_IDX] = self.hours_wid.value
alarm[_MIN_IDX] = self.min_wid.value
for day_idx, day_btn in enumerate(self.day_btns):
if day_btn.state:
alarm[_ENABLED_IDX] |= 1 << day_idx
else:
alarm[_ENABLED_IDX] &= ~(1 << day_idx)
self.page = _HOME_PAGE
def _draw(self, update_alarm_row=-1):
if self.page == _RINGING_PAGE:
self._draw_ringing_page()
elif self.page > _HOME_PAGE:
self._draw_edit_page()
else:
self._draw_home_page(update_alarm_row)
def _draw_ringing_page(self):
draw = wasp.watch.drawable
draw.set_color(wasp.system.theme('bright'))
draw.fill()
draw.set_font(fonts.sans24)
draw.string("Alarm", 0, 150, width=240)
draw.blit(icon, 73, 50)
draw.line(35, 1, 35, 239)
draw.string('Z', 10, 80)
draw.string('z', 10, 110)
draw.string('z', 10, 140)
def _draw_edit_page(self):
draw = wasp.watch.drawable
alarm = self.alarms[self.page]
draw.fill()
self._draw_system_bar()
self.hours_wid.value = alarm[_HOUR_IDX]
self.min_wid.value = alarm[_MIN_IDX]
draw.set_font(fonts.sans28)
draw.string(':', 110, 90-14, width=20)
self.del_alarm_btn.draw()
self.hours_wid.draw()
self.min_wid.draw()
for day_idx, day_btn in enumerate(self.day_btns):
day_btn.state = alarm[_ENABLED_IDX] & (1 << day_idx)
day_btn.draw()
def _draw_home_page(self, update_alarm_row=_HOME_PAGE):
draw = wasp.watch.drawable
if update_alarm_row == _HOME_PAGE:
draw.set_color(wasp.system.theme('bright'))
draw.fill()
draw.set_font(fonts.sans24)
draw.string("Alarm", 0, 150, width=240)
draw.blit(icon, 73, 50)
self._draw_system_bar()
draw.line(0, 50, 240, 50, width=1, color=wasp.system.theme('bright'))
for index in range(len(self.alarms)):
if index < self.num_alarms and (update_alarm_row == _HOME_PAGE or update_alarm_row == index):
self._draw_alarm_row(index)
elif index == self.num_alarms:
# Draw the add button
draw.set_color(wasp.system.theme('bright'))
draw.set_font(fonts.sans28)
draw.string('+', 100, 60 + (index * 45))
def _draw_alarm_row(self, index):
draw = wasp.watch.drawable
alarm = self.alarms[index]
self.alarm_checks[index].state = alarm[_ENABLED_IDX] & _IS_ACTIVE
self.alarm_checks[index].draw()
if self.alarm_checks[index].state:
draw.set_color(wasp.system.theme('bright'))
else:
draw.set_color(wasp.system.theme('mid'))
draw.set_font(fonts.sans28)
draw.string("{:02d}:{:02d}".format(alarm[_HOUR_IDX], alarm[_MIN_IDX]), 10, 60 + (index * 45), width=120)
draw.set_font(fonts.sans18)
draw.string(self._get_repeat_code(alarm[_ENABLED_IDX]), 130, 70 + (index * 45), width=60)
draw.line(0, 95 + (index * 45), 240, 95 + (index * 45), width=1, color=wasp.system.theme('bright'))
def _draw_system_bar(self):
sbar = wasp.system.bar
sbar.clock = True
sbar.draw()
def _alert(self):
self.ringing = True
self.page = _RINGING_PAGE
wasp.system.wake()
wasp.system.switch(self)
def _set_current_alarm(self):
def _snooze(self):
now = wasp.watch.rtc.get_localtime()
yyyy = now[0]
mm = now[1]
dd = now[2]
HH = self.hours.value
MM = self.minutes.value
if HH < now[3] or (HH == now[3] and MM <= now[4]):
dd += 1
self.current_alarm = (time.mktime((yyyy, mm, dd, HH, MM, 0, 0, 0, 0)))
alarm = (now[0], now[1], now[2], now[3], now[4] + 10, now[5], 0, 0, 0)
wasp.system.set_alarm(time.mktime(alarm), self._alert)
def _silence_alarm(self):
mute = wasp.watch.display.mute
mute(True)
self._draw()
mute(False)
wasp.system.navigate(wasp.EventType.HOME)
def _set_pending_alarms(self):
now = wasp.watch.rtc.get_localtime()
for index, alarm in enumerate(self.alarms):
if index < self.num_alarms and alarm[_ENABLED_IDX] & _IS_ACTIVE:
yyyy = now[0]
mm = now[1]
dd = now[2]
HH = alarm[_HOUR_IDX]
MM = alarm[_MIN_IDX]
# If next alarm is tomorrow increment the day
if HH < now[3] or (HH == now[3] and MM <= now[4]):
dd += 1
pending_time = time.mktime((yyyy, mm, dd, HH, MM, 0, 0, 0, 0))
# If this is not a one time alarm find the next day of the week that is enabled
if alarm[_ENABLED_IDX] & ~_IS_ACTIVE != 0:
for _i in range(7):
if (1 << time.localtime(pending_time)[6]) & alarm[_ENABLED_IDX] == 0:
dd += 1
pending_time = time.mktime((yyyy, mm, dd, HH, MM, 0, 0, 0, 0))
else:
break
self.pending_alarms[index] = pending_time
wasp.system.set_alarm(pending_time, self._alert)
else:
self.pending_alarms[index] = 0.0
def _deactivate_pending_alarms(self):
now = wasp.watch.rtc.get_localtime()
now = time.mktime((now[0], now[1], now[2], now[3], now[4], now[5], 0, 0, 0))
for index, alarm in enumerate(self.alarms):
pending_alarm = self.pending_alarms[index]
if not pending_alarm == 0.0:
wasp.system.cancel_alarm(pending_alarm, self._alert)
# If this is a one time alarm and in the past disable it
if alarm[_ENABLED_IDX] & ~_IS_ACTIVE == 0 and pending_alarm <= now:
alarm[_ENABLED_IDX] = 0
@staticmethod
def _get_repeat_code(days):
# Ignore the is_active bit
days = days & ~_IS_ACTIVE
if days == _WEEKDAYS:
return "wkds"
elif days == _WEEKENDS:
return "wkns"
elif days == _EVERY_DAY:
return "evry"
elif days == 0:
return "once"
else:
return "cust"

View File

@ -1,6 +1,6 @@
# Code generated by font_to_py.py.
# Font: DejaVuSans.ttf
# Cmd: ./tools/micropython-font-to-py/font_to_py.py /usr/share/fonts/dejavu/DejaVuSans.ttf --xmap 28 -e 58 -s 48 -l 58 wasp/fonts/sans28.py
# Font: DejaVuSans.ttf Char set: +-0123456789:
# Cmd: tools/micropython-font-to-py/font_to_py.py /usr/share/fonts/dejavu/DejaVuSans.ttf --xmap 28 -e 58 -c 0123456789:+- wasp/fonts/sans28.py
version = '0.33'
def height():
@ -10,7 +10,7 @@ def baseline():
return 27
def max_width():
return 24
return 31
def hmap():
return True
@ -22,7 +22,7 @@ def monospaced():
return False
def min_ch():
return 48
return 43
def max_ch():
return 58
@ -31,66 +31,78 @@ _font =\
b'\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00'\
b'\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x18\x00\x00\xfe\x00\x03\xff\x80'\
b'\x07\xff\xc0\x0f\x83\xe0\x0f\x01\xe0\x1e\x00\xf0\x1e\x00\xf0\x1e'\
b'\x00\xf0\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00'\
b'\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x1f\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x80\x00\x00\x03'\
b'\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03'\
b'\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03'\
b'\x80\x00\x0f\xff\xff\xe0\x0f\xff\xff\xe0\x0f\xff\xff\xe0\x00\x03'\
b'\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03'\
b'\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03'\
b'\x80\x00\x00\x03\x80\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x3f\xf0\x3f\xf0\x3f\xf0\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00'\
b'\x00\xfe\x00\x03\xff\x80\x07\xff\xc0\x0f\x83\xe0\x0f\x01\xe0\x1e'\
b'\x00\xf0\x1e\x00\xf0\x1e\x00\xf0\x3c\x00\x78\x3c\x00\x78\x3c\x00'\
b'\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78'\
b'\x3c\x00\x78\x1e\x00\xf0\x1e\x00\xf0\x1e\x00\xf0\x0f\x01\xe0\x0f'\
b'\x83\xe0\x07\xff\xc0\x03\xff\x80\x00\xfe\x00\x18\x00\x00\xfe\x00'\
b'\x07\xfe\x00\x07\xfe\x00\x07\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00'\
b'\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x1e\x00\xf0\x1e\x00\xf0\x1e'\
b'\x00\xf0\x0f\x01\xe0\x0f\x83\xe0\x07\xff\xc0\x03\xff\x80\x00\xfe'\
b'\x00\x18\x00\x00\xfe\x00\x07\xfe\x00\x07\xfe\x00\x07\x1e\x00\x00'\
b'\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e'\
b'\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00'\
b'\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00'\
b'\x1e\x00\x00\x1e\x00\x07\xff\xf8\x07\xff\xf8\x07\xff\xf8\x18\x00'\
b'\x01\xfc\x00\x0f\xff\x80\x1f\xff\xc0\x1f\x07\xe0\x18\x01\xe0\x10'\
b'\x01\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01'\
b'\xf0\x00\x01\xe0\x00\x03\xe0\x00\x07\xc0\x00\x0f\x80\x00\x1f\x00'\
b'\x00\x3e\x00\x00\x7e\x00\x00\xfc\x00\x01\xf8\x00\x03\xf0\x00\x07'\
b'\xe0\x00\x0f\xc0\x00\x1f\x80\x00\x1f\xff\xf0\x1f\xff\xf0\x1f\xff'\
b'\xf0\x18\x00\x03\xfe\x00\x0f\xff\x80\x0f\xff\xc0\x0c\x03\xe0\x00'\
b'\x01\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01'\
b'\xe0\x00\x03\xc0\x00\xff\x80\x00\xfe\x00\x00\xff\xc0\x00\x03\xe0'\
b'\x00\x00\xf0\x00\x00\xf8\x00\x00\x78\x00\x00\x78\x00\x00\x78\x00'\
b'\x00\x78\x00\x00\xf8\x00\x01\xf0\x18\x03\xf0\x1f\xff\xe0\x1f\xff'\
b'\x80\x07\xfe\x00\x18\x00\x00\x07\xc0\x00\x0f\xc0\x00\x0f\xc0\x00'\
b'\x1f\xc0\x00\x3b\xc0\x00\x3b\xc0\x00\x73\xc0\x00\xf3\xc0\x00\xe3'\
b'\xc0\x01\xc3\xc0\x03\xc3\xc0\x03\x83\xc0\x07\x03\xc0\x07\x03\xc0'\
b'\x0e\x03\xc0\x1e\x03\xc0\x1c\x03\xc0\x38\x03\xc0\x3f\xff\xfc\x3f'\
b'\xff\xfc\x3f\xff\xfc\x00\x03\xc0\x00\x03\xc0\x00\x03\xc0\x00\x03'\
b'\xc0\x00\x03\xc0\x00\x03\xc0\x18\x00\x0f\xff\xc0\x0f\xff\xc0\x0f'\
b'\xff\xc0\x0f\x00\x00\x0f\x00\x00\x0f\x00\x00\x0f\x00\x00\x0f\x00'\
b'\x00\x0f\x00\x00\x0f\xfc\x00\x0f\xff\x00\x0f\xff\xc0\x0c\x0f\xc0'\
b'\x00\x03\xe0\x00\x01\xe0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00'\
b'\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01\xe0\x00\x03\xe0\x18\x07'\
b'\xc0\x1f\xff\xc0\x1f\xff\x00\x07\xfc\x00\x18\x00\x00\x3f\x80\x00'\
b'\xff\xe0\x03\xff\xe0\x07\xe0\x60\x0f\x80\x00\x0f\x00\x00\x1f\x00'\
b'\x00\x1e\x00\x00\x1e\x00\x00\x3c\x00\x00\x3c\x7f\x00\x3c\xff\xc0'\
b'\x3d\xff\xe0\x3f\x83\xf0\x3e\x00\xf0\x3e\x00\xf8\x3c\x00\x78\x3c'\
b'\x00\x78\x3c\x00\x78\x1c\x00\x78\x1c\x00\x78\x1e\x00\xf8\x0e\x00'\
b'\xf0\x0f\x83\xf0\x07\xff\xe0\x03\xff\x80\x00\xfe\x00\x18\x00\x1f'\
b'\xff\xf0\x1f\xff\xf0\x1f\xff\xf0\x00\x01\xe0\x00\x01\xe0\x00\x03'\
b'\xe0\x00\x03\xc0\x00\x03\xc0\x00\x07\xc0\x00\x07\x80\x00\x07\x80'\
b'\x00\x0f\x80\x00\x0f\x00\x00\x0f\x00\x00\x1f\x00\x00\x1e\x00\x00'\
b'\x1e\x00\x00\x3e\x00\x00\x3c\x00\x00\x3c\x00\x00\x78\x00\x00\x78'\
b'\x00\x00\x78\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01\xe0\x00'\
b'\x18\x00\x00\xfe\x00\x03\xff\x80\x0f\xff\xe0\x0f\x83\xe0\x1f\x01'\
b'\xf0\x1e\x00\xf0\x1e\x00\xf0\x1e\x00\xf0\x1e\x00\xf0\x0f\x01\xe0'\
b'\x07\x83\xc0\x03\xff\x80\x00\xfe\x00\x07\xff\xc0\x0f\x83\xe0\x1e'\
b'\x00\xf0\x3e\x00\xf0\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00'\
b'\x78\x3e\x00\xf8\x1e\x00\xf0\x1f\x83\xf0\x0f\xff\xe0\x07\xff\xc0'\
b'\x00\xfe\x00\x18\x00\x00\xfe\x00\x03\xff\x00\x0f\xff\xc0\x1f\x83'\
b'\xe0\x1e\x00\xe0\x3e\x00\xf0\x3c\x00\x70\x3c\x00\x70\x3c\x00\x78'\
b'\x3c\x00\x78\x3c\x00\x78\x3e\x00\xf8\x1e\x00\xf8\x1f\x83\xf8\x0f'\
b'\xff\x78\x07\xfe\x78\x01\xfc\x78\x00\x00\xf8\x00\x00\xf0\x00\x00'\
b'\xf0\x00\x01\xf0\x00\x01\xe0\x00\x03\xe0\x0c\x0f\xc0\x0f\xff\x80'\
b'\x0f\xfe\x00\x03\xf8\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00'\
b'\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00'
b'\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x07\xff\xf8\x07\xff'\
b'\xf8\x07\xff\xf8\x18\x00\x01\xfc\x00\x0f\xff\x80\x1f\xff\xc0\x1f'\
b'\x07\xe0\x18\x01\xe0\x10\x01\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00'\
b'\xf0\x00\x00\xf0\x00\x01\xf0\x00\x01\xe0\x00\x03\xe0\x00\x07\xc0'\
b'\x00\x0f\x80\x00\x1f\x00\x00\x3e\x00\x00\x7e\x00\x00\xfc\x00\x01'\
b'\xf8\x00\x03\xf0\x00\x07\xe0\x00\x0f\xc0\x00\x1f\x80\x00\x1f\xff'\
b'\xf0\x1f\xff\xf0\x1f\xff\xf0\x18\x00\x03\xfe\x00\x0f\xff\x80\x0f'\
b'\xff\xc0\x0c\x03\xe0\x00\x01\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00'\
b'\xf0\x00\x00\xf0\x00\x01\xe0\x00\x03\xc0\x00\xff\x80\x00\xfe\x00'\
b'\x00\xff\xc0\x00\x03\xe0\x00\x00\xf0\x00\x00\xf8\x00\x00\x78\x00'\
b'\x00\x78\x00\x00\x78\x00\x00\x78\x00\x00\xf8\x00\x01\xf0\x18\x03'\
b'\xf0\x1f\xff\xe0\x1f\xff\x80\x07\xfe\x00\x18\x00\x00\x07\xc0\x00'\
b'\x0f\xc0\x00\x0f\xc0\x00\x1f\xc0\x00\x3b\xc0\x00\x3b\xc0\x00\x73'\
b'\xc0\x00\xf3\xc0\x00\xe3\xc0\x01\xc3\xc0\x03\xc3\xc0\x03\x83\xc0'\
b'\x07\x03\xc0\x07\x03\xc0\x0e\x03\xc0\x1e\x03\xc0\x1c\x03\xc0\x38'\
b'\x03\xc0\x3f\xff\xfc\x3f\xff\xfc\x3f\xff\xfc\x00\x03\xc0\x00\x03'\
b'\xc0\x00\x03\xc0\x00\x03\xc0\x00\x03\xc0\x00\x03\xc0\x18\x00\x0f'\
b'\xff\xc0\x0f\xff\xc0\x0f\xff\xc0\x0f\x00\x00\x0f\x00\x00\x0f\x00'\
b'\x00\x0f\x00\x00\x0f\x00\x00\x0f\x00\x00\x0f\xfc\x00\x0f\xff\x00'\
b'\x0f\xff\xc0\x0c\x0f\xc0\x00\x03\xe0\x00\x01\xe0\x00\x00\xf0\x00'\
b'\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01'\
b'\xe0\x00\x03\xe0\x18\x07\xc0\x1f\xff\xc0\x1f\xff\x00\x07\xfc\x00'\
b'\x18\x00\x00\x3f\x80\x00\xff\xe0\x03\xff\xe0\x07\xe0\x60\x0f\x80'\
b'\x00\x0f\x00\x00\x1f\x00\x00\x1e\x00\x00\x1e\x00\x00\x3c\x00\x00'\
b'\x3c\x7f\x00\x3c\xff\xc0\x3d\xff\xe0\x3f\x83\xf0\x3e\x00\xf0\x3e'\
b'\x00\xf8\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x1c\x00\x78\x1c\x00'\
b'\x78\x1e\x00\xf8\x0e\x00\xf0\x0f\x83\xf0\x07\xff\xe0\x03\xff\x80'\
b'\x00\xfe\x00\x18\x00\x1f\xff\xf0\x1f\xff\xf0\x1f\xff\xf0\x00\x01'\
b'\xe0\x00\x01\xe0\x00\x03\xe0\x00\x03\xc0\x00\x03\xc0\x00\x07\xc0'\
b'\x00\x07\x80\x00\x07\x80\x00\x0f\x80\x00\x0f\x00\x00\x0f\x00\x00'\
b'\x1f\x00\x00\x1e\x00\x00\x1e\x00\x00\x3e\x00\x00\x3c\x00\x00\x3c'\
b'\x00\x00\x78\x00\x00\x78\x00\x00\x78\x00\x00\xf0\x00\x00\xf0\x00'\
b'\x00\xf0\x00\x01\xe0\x00\x18\x00\x00\xfe\x00\x03\xff\x80\x0f\xff'\
b'\xe0\x0f\x83\xe0\x1f\x01\xf0\x1e\x00\xf0\x1e\x00\xf0\x1e\x00\xf0'\
b'\x1e\x00\xf0\x0f\x01\xe0\x07\x83\xc0\x03\xff\x80\x00\xfe\x00\x07'\
b'\xff\xc0\x0f\x83\xe0\x1e\x00\xf0\x3e\x00\xf0\x3c\x00\x78\x3c\x00'\
b'\x78\x3c\x00\x78\x3c\x00\x78\x3e\x00\xf8\x1e\x00\xf0\x1f\x83\xf0'\
b'\x0f\xff\xe0\x07\xff\xc0\x00\xfe\x00\x18\x00\x00\xfe\x00\x03\xff'\
b'\x00\x0f\xff\xc0\x1f\x83\xe0\x1e\x00\xe0\x3e\x00\xf0\x3c\x00\x70'\
b'\x3c\x00\x70\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3e\x00\xf8\x1e'\
b'\x00\xf8\x1f\x83\xf8\x0f\xff\x78\x07\xfe\x78\x01\xfc\x78\x00\x00'\
b'\xf8\x00\x00\xf0\x00\x00\xf0\x00\x01\xf0\x00\x01\xe0\x00\x03\xe0'\
b'\x0c\x0f\xc0\x0f\xff\x80\x0f\xfe\x00\x03\xf8\x00\x0c\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00'\
b'\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x0f\x00\x0f\x00'\
b'\x0f\x00\x0f\x00'
_index =\
b'\x00\x00\x38\x00\x8b\x00\xde\x00\x31\x01\x84\x01\xd7\x01\x2a\x02'\
b'\x7d\x02\xd0\x02\x23\x03\x76\x03\xae\x03'
b'\x00\x00\x38\x00\x00\x00\xa6\x00\x00\x00\x00\x00\xde\x00\x31\x01'\
b'\x84\x01\xd7\x01\x2a\x02\x7d\x02\xd0\x02\x23\x03\x76\x03\xc9\x03'\
b'\x1c\x04\x54\x04'
_mvfont = memoryview(_font)
_mvi = memoryview(_index)
@ -98,7 +110,7 @@ ifb = lambda l : l[0] | (l[1] << 8)
def get_ch(ch):
oc = ord(ch)
ioff = 2 * (oc - 48 + 1) if oc >= 48 and oc <= 58 else 0
ioff = 2 * (oc - 43 + 1) if oc >= 43 and oc <= 58 else 0
doff = ifb(_mvi[ioff : ])
width = ifb(_mvfont[doff : ])

View File

@ -1,6 +1,6 @@
# Code generated by font_to_py.py.
# Font: DejaVuSans.ttf
# Cmd: tools/micropython-font-to-py/font_to_py.py /usr/share/fonts/dejavu/DejaVuSans.ttf --xmap 36 -e 58 -s 48 -l 58 wasp/fonts/sans36.py
# Font: DejaVuSans.ttf Char set: +-0123456789:
# Cmd: tools/micropython-font-to-py/font_to_py.py /usr/share/fonts/dejavu/DejaVuSans.ttf --xmap 36 -e 58 -c 0123456789:+- wasp/fonts/sans36.py
version = '0.33'
def height():
@ -10,7 +10,7 @@ def baseline():
return 35
def max_width():
return 30
return 39
def hmap():
return True
@ -22,7 +22,7 @@ def monospaced():
return False
def min_ch():
return 48
return 43
def max_ch():
return 58
@ -32,107 +32,126 @@ b'\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x03\xe0\x03\xe0\x03\xe0\x03\xe0'\
b'\x03\xe0\x03\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xe0\x03\xe0'\
b'\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x00\x00\x1e\x00\x00\x0f\xc0\x00'\
b'\x00\x7f\xf8\x00\x00\xff\xfc\x00\x01\xff\xfe\x00\x03\xf0\x3f\x00'\
b'\x03\xe0\x1f\x00\x07\xc0\x0f\x80\x07\x80\x07\x80\x0f\x80\x07\xc0'\
b'\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x1e\x00\x01\xe0'\
b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\
b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\
b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x0f\x00\x03\xc0'\
b'\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x07\xc0\x07\x80\x07\x80'\
b'\x07\xc0\x0f\x80\x07\xe0\x1f\x00\x03\xf0\x3f\x00\x01\xff\xfe\x00'\
b'\x00\xff\xfc\x00\x00\x7f\xf8\x00\x00\x1f\xe0\x00\x1e\x00\x00\x00'\
b'\x00\x00\x00\x1f\x80\x00\x01\xff\x80\x00\x07\xff\x80\x00\x07\xff'\
b'\x80\x00\x07\xe7\x80\x00\x06\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x07\xff\xff\x80\x07\xff'\
b'\xff\x80\x07\xff\xff\x80\x07\xff\xff\x80\x00\x00\x00\x00\x1e\x00'\
b'\x00\x7f\xc0\x00\x03\xff\xf8\x00\x0f\xff\xfc\x00\x0f\xff\xff\x00'\
b'\x0f\xe0\x3f\x00\x0e\x00\x0f\x80\x08\x00\x07\x80\x00\x00\x07\xc0'\
b'\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0'\
b'\x00\x00\x03\xc0\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00\x0f\x00'\
b'\x00\x00\x1f\x00\x00\x00\x3e\x00\x00\x00\x7c\x00\x00\x00\xf8\x00'\
b'\x00\x01\xf0\x00\x00\x03\xe0\x00\x00\x07\xc0\x00\x00\x0f\x80\x00'\
b'\x00\x1f\x00\x00\x00\x3e\x00\x00\x00\x7c\x00\x00\x00\xf8\x00\x00'\
b'\x01\xf0\x00\x00\x03\xe0\x00\x00\x07\xc0\x00\x00\x0f\xff\xff\xc0'\
b'\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x00\x00\x00\x00'\
b'\x1e\x00\x00\xff\xe0\x00\x07\xff\xf8\x00\x07\xff\xfe\x00\x07\xff'\
b'\xff\x00\x07\x00\x3f\x80\x00\x00\x0f\x80\x00\x00\x07\xc0\x00\x00'\
b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00'\
b'\x03\xc0\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00\x3f\x00\x00\x3f'\
b'\xfe\x00\x00\x3f\xf8\x00\x00\x3f\xfc\x00\x00\x3f\xff\x00\x00\x00'\
b'\x3f\x80\x00\x00\x0f\xc0\x00\x00\x03\xc0\x00\x00\x03\xe0\x00\x00'\
b'\x01\xe0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00'\
b'\x01\xe0\x00\x00\x03\xe0\x00\x00\x07\xc0\x08\x00\x0f\xc0\x0f\x00'\
b'\x3f\x80\x0f\xff\xff\x00\x0f\xff\xfe\x00\x07\xff\xf8\x00\x00\x7f'\
b'\xc0\x00\x1e\x00\x00\x00\x00\x00\x00\x00\xfc\x00\x00\x01\xfc\x00'\
b'\x00\x01\xfc\x00\x00\x03\xfc\x00\x00\x07\xbc\x00\x00\x07\x3c\x00'\
b'\x00\x0f\x3c\x00\x00\x1e\x3c\x00\x00\x1e\x3c\x00\x00\x3c\x3c\x00'\
b'\x00\x78\x3c\x00\x00\x78\x3c\x00\x00\xf0\x3c\x00\x01\xe0\x3c\x00'\
b'\x01\xe0\x3c\x00\x03\xc0\x3c\x00\x07\x80\x3c\x00\x07\x80\x3c\x00'\
b'\x0f\x00\x3c\x00\x1f\x00\x3c\x00\x1e\x00\x3c\x00\x3c\x00\x3c\x00'\
b'\x3f\xff\xff\xe0\x3f\xff\xff\xe0\x3f\xff\xff\xe0\x3f\xff\xff\xe0'\
b'\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00'\
b'\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00'\
b'\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x07\xff\xfe\x00\x07\xff'\
b'\xfe\x00\x07\xff\xfe\x00\x07\xff\xfe\x00\x07\x80\x00\x00\x07\x80'\
b'\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80'\
b'\x00\x00\x07\x80\x00\x00\x07\xbf\x80\x00\x07\xff\xf0\x00\x07\xff'\
b'\xfc\x00\x07\xff\xfe\x00\x07\x80\xff\x00\x04\x00\x1f\x00\x00\x00'\
b'\x0f\x80\x00\x00\x07\x80\x00\x00\x07\xc0\x00\x00\x03\xc0\x00\x00'\
b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00'\
b'\x03\xc0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00\x0f\x80\x08\x00'\
b'\x1f\x00\x0f\x00\x7f\x00\x0f\xff\xfe\x00\x0f\xff\xfc\x00\x0f\xff'\
b'\xf0\x00\x01\xff\x80\x00\x1e\x00\x00\x03\xfe\x00\x00\x1f\xff\x80'\
b'\x00\x7f\xff\x80\x00\xff\xff\x80\x01\xfc\x01\x80\x03\xf0\x00\x00'\
b'\x03\xe0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00\x0f\x00\x00\x00'\
b'\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x0f\xe0\x00\x1e\x3f\xfc\x00'\
b'\x1e\x7f\xfe\x00\x1e\xff\xff\x00\x1f\xf8\x3f\x80\x1f\xe0\x0f\x80'\
b'\x1f\xc0\x07\xc0\x1f\x80\x03\xc0\x1f\x80\x03\xe0\x1f\x00\x01\xe0'\
b'\x1f\x00\x01\xe0\x1f\x00\x01\xe0\x0f\x00\x01\xe0\x0f\x00\x01\xe0'\
b'\x0f\x00\x01\xe0\x0f\x80\x03\xe0\x07\x80\x03\xc0\x07\xc0\x07\xc0'\
b'\x03\xe0\x0f\x80\x03\xf8\x3f\x80\x01\xff\xff\x00\x00\xff\xfe\x00'\
b'\x00\x7f\xfc\x00\x00\x0f\xe0\x00\x1e\x00\x00\x00\x00\x00\x0f\xff'\
b'\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\x80\x00\x00'\
b'\x07\x80\x00\x00\x0f\x80\x00\x00\x0f\x00\x00\x00\x1f\x00\x00\x00'\
b'\x1e\x00\x00\x00\x1e\x00\x00\x00\x3e\x00\x00\x00\x3c\x00\x00\x00'\
b'\x3c\x00\x00\x00\x78\x00\x00\x00\x78\x00\x00\x00\xf8\x00\x00\x00'\
b'\xf0\x00\x00\x00\xf0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00\x03'\
b'\xe0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x0f\x80\x00\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x1e'\
b'\x00\x00\x00\x1e\x00\x00\x00\x3e\x00\x00\x00\x3c\x00\x00\x00\x3c'\
b'\x00\x00\x00\x78\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x1f\xe0\x00'\
b'\x00\xff\xfc\x00\x01\xff\xfe\x00\x03\xff\xff\x00\x07\xf0\x3f\x80'\
b'\x07\xc0\x0f\x80\x0f\x80\x07\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0'\
b'\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x07\x80\x07\x80'\
b'\x07\xc0\x0f\x80\x03\xf0\x3f\x00\x01\xff\xfe\x00\x00\x7f\xf8\x00'\
b'\x00\xff\xfc\x00\x03\xff\xff\x00\x07\xe0\x1f\x80\x0f\x80\x07\xc0'\
b'\x0f\x00\x03\xc0\x1f\x00\x03\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\
b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1f\x00\x03\xe0'\
b'\x0f\x00\x03\xc0\x0f\x80\x07\xc0\x0f\xe0\x1f\x80\x07\xff\xff\x80'\
b'\x03\xff\xff\x00\x00\xff\xfc\x00\x00\x1f\xe0\x00\x1e\x00\x00\x1f'\
b'\xc0\x00\x00\xff\xf0\x00\x01\xff\xfc\x00\x03\xff\xfe\x00\x07\xf0'\
b'\x7f\x00\x0f\xc0\x1f\x00\x0f\x80\x0f\x80\x0f\x00\x07\x80\x1f\x00'\
b'\x07\xc0\x1e\x00\x03\xc0\x1e\x00\x03\xc0\x1e\x00\x03\xc0\x1e\x00'\
b'\x03\xe0\x1e\x00\x03\xe0\x1e\x00\x03\xe0\x1f\x00\x07\xe0\x0f\x00'\
b'\x07\xe0\x0f\x80\x0f\xe0\x0f\xc0\x1f\xe0\x07\xf0\x7f\xe0\x03\xff'\
b'\xfd\xe0\x01\xff\xf9\xe0\x00\xff\xf1\xe0\x00\x1f\xc3\xc0\x00\x00'\
b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00'\
b'\x0f\x80\x00\x00\x1f\x00\x00\x00\x3f\x00\x06\x00\xfe\x00\x07\xff'\
b'\xfc\x00\x07\xff\xf8\x00\x07\xff\xe0\x00\x01\xff\x00\x00\x10\x00'\
b'\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x00\x00\x27\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xe0'\
b'\x03\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00'\
b'\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00'\
b'\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c'\
b'\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00'\
b'\x00\x00\x00\x3c\x00\x00\x07\xff\xff\xff\xe0\x07\xff\xff\xff\xe0'\
b'\x07\xff\xff\xff\xe0\x07\xff\xff\xff\xe0\x00\x00\x3c\x00\x00\x00'\
b'\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00'\
b'\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c'\
b'\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00'\
b'\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x00\x00'\
b'\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xfc'\
b'\x00\x3f\xfc\x00\x3f\xfc\x00\x3f\xfc\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x00'\
b'\x00\x0f\xc0\x00\x00\x7f\xf8\x00\x00\xff\xfc\x00\x01\xff\xfe\x00'\
b'\x03\xf0\x3f\x00\x03\xe0\x1f\x00\x07\xc0\x0f\x80\x07\x80\x07\x80'\
b'\x0f\x80\x07\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x1f\x00\x03\xc0'\
b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\
b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\
b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\
b'\x1f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x80\x07\xc0'\
b'\x07\x80\x07\x80\x07\xc0\x0f\x80\x03\xe0\x1f\x00\x03\xf0\x3f\x00'\
b'\x01\xff\xfe\x00\x00\xff\xfc\x00\x00\x7f\xf8\x00\x00\x1f\xc0\x00'\
b'\x1e\x00\x00\x00\x00\x00\x00\x1f\x80\x00\x01\xff\x80\x00\x07\xff'\
b'\x80\x00\x07\xff\x80\x00\x07\xe7\x80\x00\x06\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x07\xff'\
b'\xff\x80\x07\xff\xff\x80\x07\xff\xff\x80\x07\xff\xff\x80\x00\x00'\
b'\x00\x00\x1e\x00\x00\x7f\xc0\x00\x03\xff\xf8\x00\x0f\xff\xfe\x00'\
b'\x0f\xff\xff\x00\x0f\xe0\x3f\x00\x0e\x00\x0f\x80\x08\x00\x07\x80'\
b'\x00\x00\x07\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0'\
b'\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\x80\x00\x00\x0f\x80'\
b'\x00\x00\x0f\x00\x00\x00\x1f\x00\x00\x00\x3e\x00\x00\x00\x7c\x00'\
b'\x00\x00\xf8\x00\x00\x01\xf0\x00\x00\x03\xe0\x00\x00\x07\xc0\x00'\
b'\x00\x0f\x80\x00\x00\x1f\x00\x00\x00\x3e\x00\x00\x00\x7c\x00\x00'\
b'\x00\xf8\x00\x00\x01\xf0\x00\x00\x03\xe0\x00\x00\x07\xc0\x00\x00'\
b'\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0'\
b'\x00\x00\x00\x00\x1e\x00\x00\xff\xe0\x00\x07\xff\xf8\x00\x07\xff'\
b'\xfe\x00\x07\xff\xff\x00\x07\x00\x3f\x80\x00\x00\x0f\x80\x00\x00'\
b'\x07\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00'\
b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00'\
b'\x3f\x00\x00\x3f\xfe\x00\x00\x3f\xf8\x00\x00\x3f\xfc\x00\x00\x3f'\
b'\xff\x00\x00\x00\x3f\x80\x00\x00\x0f\xc0\x00\x00\x03\xc0\x00\x00'\
b'\x03\xe0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00'\
b'\x01\xe0\x00\x00\x01\xe0\x00\x00\x03\xe0\x00\x00\x07\xc0\x08\x00'\
b'\x0f\xc0\x0f\x00\x3f\x80\x0f\xff\xff\x00\x0f\xff\xfe\x00\x07\xff'\
b'\xf8\x00\x00\x7f\xc0\x00\x1e\x00\x00\x00\x00\x00\x00\x00\xfc\x00'\
b'\x00\x01\xfc\x00\x00\x01\xfc\x00\x00\x03\xfc\x00\x00\x07\xbc\x00'\
b'\x00\x07\x3c\x00\x00\x0f\x3c\x00\x00\x1e\x3c\x00\x00\x1e\x3c\x00'\
b'\x00\x3c\x3c\x00\x00\x78\x3c\x00\x00\x78\x3c\x00\x00\xf0\x3c\x00'\
b'\x01\xe0\x3c\x00\x01\xe0\x3c\x00\x03\xc0\x3c\x00\x07\x80\x3c\x00'\
b'\x07\x80\x3c\x00\x0f\x00\x3c\x00\x1f\x00\x3c\x00\x1e\x00\x3c\x00'\
b'\x3c\x00\x3c\x00\x3f\xff\xff\xe0\x3f\xff\xff\xe0\x3f\xff\xff\xe0'\
b'\x3f\xff\xff\xe0\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00'\
b'\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00'\
b'\x00\x00\x3c\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x07\xff'\
b'\xfe\x00\x07\xff\xfe\x00\x07\xff\xfe\x00\x07\xff\xfe\x00\x07\x80'\
b'\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80'\
b'\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\xbf\x80\x00\x07\xff'\
b'\xf0\x00\x07\xff\xfc\x00\x07\xff\xfe\x00\x07\x80\xff\x00\x04\x00'\
b'\x1f\x00\x00\x00\x0f\x80\x00\x00\x07\x80\x00\x00\x07\xc0\x00\x00'\
b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00'\
b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00'\
b'\x0f\x80\x08\x00\x1f\x00\x0f\x00\x7f\x00\x0f\xff\xfe\x00\x0f\xff'\
b'\xfc\x00\x0f\xff\xf0\x00\x01\xff\x80\x00\x1e\x00\x00\x03\xfe\x00'\
b'\x00\x1f\xff\x80\x00\x7f\xff\x80\x00\xff\xff\x80\x01\xfc\x01\x80'\
b'\x03\xf0\x00\x00\x03\xc0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00'\
b'\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x1f\x0f\xe0\x00'\
b'\x1e\x3f\xfc\x00\x1e\x7f\xfe\x00\x1e\xff\xff\x00\x1f\xf8\x3f\x80'\
b'\x1f\xe0\x0f\xc0\x1f\xc0\x07\xc0\x1f\x80\x03\xc0\x1f\x80\x03\xe0'\
b'\x1f\x00\x01\xe0\x1f\x00\x01\xe0\x1f\x00\x01\xe0\x0f\x00\x01\xe0'\
b'\x0f\x00\x01\xe0\x0f\x00\x01\xe0\x0f\x80\x03\xe0\x07\x80\x03\xc0'\
b'\x07\xc0\x07\xc0\x03\xe0\x0f\x80\x03\xf8\x3f\x80\x01\xff\xff\x00'\
b'\x00\xff\xfe\x00\x00\x7f\xfc\x00\x00\x0f\xe0\x00\x1e\x00\x00\x00'\
b'\x00\x00\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff'\
b'\xff\x80\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00\x0f\x00\x00\x00'\
b'\x1f\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x00\x3e\x00\x00\x00'\
b'\x3c\x00\x00\x00\x3c\x00\x00\x00\x78\x00\x00\x00\x78\x00\x00\x00'\
b'\xf8\x00\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x01\xe0\x00\x00\x01'\
b'\xe0\x00\x00\x03\xe0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00\x0f\x00\x00\x00\x0f'\
b'\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x00\x3e\x00\x00\x00\x3c'\
b'\x00\x00\x00\x3c\x00\x00\x00\x78\x00\x00\x00\x00\x00\x00\x1e\x00'\
b'\x00\x1f\xe0\x00\x00\xff\xfc\x00\x01\xff\xfe\x00\x03\xff\xff\x00'\
b'\x07\xf0\x3f\x80\x07\xc0\x0f\x80\x0f\x80\x07\xc0\x0f\x00\x03\xc0'\
b'\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0'\
b'\x07\x80\x07\x80\x07\xc0\x0f\x80\x03\xf0\x3f\x00\x01\xff\xfe\x00'\
b'\x00\x7f\xf8\x00\x00\xff\xfc\x00\x03\xff\xff\x00\x07\xe0\x1f\x80'\
b'\x0f\x80\x07\xc0\x0f\x00\x03\xc0\x1f\x00\x03\xe0\x1e\x00\x01\xe0'\
b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\
b'\x1f\x00\x03\xe0\x0f\x00\x03\xc0\x0f\x80\x07\xc0\x07\xe0\x1f\x80'\
b'\x07\xff\xff\x80\x03\xff\xff\x00\x00\xff\xfc\x00\x00\x1f\xe0\x00'\
b'\x1e\x00\x00\x1f\xc0\x00\x00\xff\xf8\x00\x01\xff\xfc\x00\x03\xff'\
b'\xfe\x00\x07\xf0\x7f\x00\x0f\xc0\x1f\x00\x0f\x80\x0f\x80\x0f\x00'\
b'\x07\x80\x1f\x00\x07\xc0\x1e\x00\x03\xc0\x1e\x00\x03\xc0\x1e\x00'\
b'\x03\xc0\x1e\x00\x03\xe0\x1e\x00\x03\xe0\x1e\x00\x03\xe0\x1f\x00'\
b'\x07\xe0\x0f\x00\x07\xe0\x0f\x80\x0f\xe0\x0f\xc0\x1f\xe0\x07\xf0'\
b'\x7f\xe0\x03\xff\xfd\xe0\x01\xff\xf9\xe0\x00\xff\xf1\xe0\x00\x1f'\
b'\xc3\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\xc0\x00\x00'\
b'\x07\x80\x00\x00\x0f\x80\x00\x00\x1f\x00\x00\x00\x3f\x00\x06\x00'\
b'\xfe\x00\x07\xff\xfc\x00\x07\xff\xf8\x00\x07\xff\xe0\x00\x01\xff'\
b'\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xe0\x03\xe0\x03\xe0'\
b'\x03\xe0\x03\xe0\x03\xe0\x00\x00'
b'\x03\xe0\x03\xe0\x03\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xe0'\
b'\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x00\x00'
_index =\
b'\x00\x00\x4a\x00\xdc\x00\x6e\x01\x00\x02\x92\x02\x24\x03\xb6\x03'\
b'\x48\x04\xda\x04\x6c\x05\xfe\x05\x48\x06'
b'\x00\x00\x4a\x00\x00\x00\x00\x01\x00\x00\x00\x00\x6e\x01\x00\x02'\
b'\x92\x02\x24\x03\xb6\x03\x48\x04\xda\x04\x6c\x05\xfe\x05\x90\x06'\
b'\x22\x07\x6c\x07'
_mvfont = memoryview(_font)
_mvi = memoryview(_index)
@ -140,7 +159,7 @@ ifb = lambda l : l[0] | (l[1] << 8)
def get_ch(ch):
oc = ord(ch)
ioff = 2 * (oc - 48 + 1) if oc >= 48 and oc <= 58 else 0
ioff = 2 * (oc - 43 + 1) if oc >= 43 and oc <= 58 else 0
doff = ifb(_mvi[ioff : ])
width = ifb(_mvfont[doff : ])

View File

@ -222,11 +222,14 @@ class Button():
def draw(self):
"""Draw the button."""
draw = wasp.watch.drawable
im = self._im
bg = draw.darken(wasp.system.theme('ui'))
bg = wasp.watch.drawable.darken(wasp.system.theme('ui'))
frame = wasp.system.theme('mid')
txt = wasp.system.theme('bright')
self.update(bg, frame, txt)
def update(self, bg, frame, txt):
draw = wasp.watch.drawable
im = self._im
draw.fill(bg, im[0], im[1], im[2], im[3])
draw.set_color(txt, bg)
@ -255,6 +258,31 @@ class Button():
return False
class ToggleButton(Button):
"""A button with a text label that can be toggled on and off."""
def __init__(self, x, y, w, h, label):
super().__init__(x, y, w, h, label)
self.state = False
def draw(self):
"""Draw the button."""
draw = wasp.watch.drawable
if self.state:
bg = draw.darken(wasp.system.theme('ui'))
else:
bg = draw.darken(wasp.system.theme('mid'))
frame = wasp.system.theme('mid')
txt = wasp.system.theme('bright')
self.update(bg, frame, txt)
def touch(self, event):
"""Handle touch events."""
if super().touch(event):
self.state = not self.state
self.draw()
class Checkbox():
"""A simple (labelled) checkbox."""
def __init__(self, x, y, label=None):
@ -294,9 +322,10 @@ class Checkbox():
def touch(self, event):
"""Handle touch events."""
x = event[1]
y = event[2]
im = self._im
if y >= im[1] and y < im[1]+40:
if (self.label or im[0] <= x < im[0]+40) and im[1] <= y < im[1]+40:
self.state = not self.state
self.update()
return True