Compare commits

..

No commits in common. "f4ad9fb4cd00dee27b925b9b7d4536b0ec160612" and "c63c29fe761347e5c7c2cede1bba8f13139f46d7" have entirely different histories.

11 changed files with 4 additions and 215 deletions

1
.gitignore vendored
View file

@ -11,4 +11,3 @@ attic/
wasp/boards/*/watch.py wasp/boards/*/watch.py
.idea .idea
.vscode .vscode
env/

View file

@ -261,7 +261,3 @@ application (and the "blank" white screen is a torch application):
.. image:: res/LevelApp.png .. image:: res/LevelApp.png
:alt: Shows a time as words in the wasp-os simulator :alt: Shows a time as words in the wasp-os simulator
:width: 179 :width: 179
.. image:: res/BeaconApp.png
:alt: Flash the relatively powerful HRS LED repeatedly
:width: 179

View file

@ -1,104 +0,0 @@
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2021 Francesco Gazzetta
"""Beacon application
~~~~~~~~~~~~~~~~~~~~~
Flash the relatively powerful HRS LED repeatedly, mostly for signaling purposes.
Frequency and intensity can be changed.
The blinking is handled by the HRS, so this app consumes very little power.
With BLE and/or step counter disabled and blinking frequency set to the minimum,
the watch's battery will last for many days.
.. figure:: res/BeaconApp.png
:width: 179
"""
import wasp
import machine
from micropython import const
class BeaconApp():
NAME = "Beacon"
# 2-bit RLE, 96x64, generated from res/beacon_icon.png, 336 bytes
ICON = (
b'\x02'
b'`@'
b'?\xff\x11@\xfcB?\x1dB\x80z\x82B?\x1aA'
b'\x86A?\x18A\x88A?\t\xc0\x18\xc3\nA\x8aA'
b'\n\xc3=\xc5\x04N\x04\xc5?\x06\xc3\x02A\xcaA\x02'
b'\xc3?\x10A\xcaA?\x08\xcb\x02A\xc3@\x1eD\xc3'
b'\x80\xfc\x81\x02\xcc9\xcb\x01\x81\xc4D\xc4\x81\x01\xcc?'
b'\x06\x81\xcc\x81?\x0f\xc3\x01\x81\xcc\x81\x01\xc3?\x06\xc5'
b'\x04\x8e\x04\xc5=\xc3\t\x81\xc0z\xcc\x81\t@\x18C'
b'?\x07\x81\xcc\x81?\x12\x81\xce\x81?\x11\x81\xce\x81?'
b'\x11\x81\xce\x81?\x11\x81\xce\x81?\x11\x81\xce\x81?\x11'
b'\x81\xce\x81?\x11\x81\xce\x81?\x10\x81\xd0\x81?\x0f\x81'
b'\xd0\x81?\x0f\x92?\x0f\x81\x80\x81\x90\xc0\xfc\xc1?\x0f'
b'\xc1\x90\xc1?\x0f\xc1\x90\xc1?\x0e\xc1\x92\xc1?\r\xc1'
b'\x92\xc1?\r\xc1\x92\xc1?\r\xc1\x92\xc1?\r\xc1\x92'
b'\xc1?\r\xc1\x92\xc1?\r\xc1\x92\xc1?\x0c\xc1\x94\xc1'
b'?\x0b\xd6?\x0b\xc1@zT\xc1?\x0b\xc1T\xc1?'
b'\x0b\xc1T\xc1?\x0b\xc1T\xc1?\n\xc1V\xc1?\t'
b'\xc1V\xc1?\t\xc1V\xc1?\t\xc1V\xc1?\t\xc1'
b'V\xc1?\t\xc1V\xc1?\t\xc1V\xc1?\x08\xda?'
b'\x07\xc1\x98\xc1?\x07\xc1\x98\xc1?\x07\xc1\x98\xc1?\x07'
b'\xc1\x98\xc1?\x07\xc1\x98\xc1?\x06\xc1\x9a\xc1?\x05\xc1'
b'\x9a\xc1?\x05\xc1\x9a\xc1?\x05\xdc?\xff\x04'
)
def __init__(self):
self._checkbox = wasp.widgets.Checkbox(10, 45, "Enable beacon")
self._slider_current = wasp.widgets.Slider(4, 10, 110, 0x27e4)
self._slider_wait_time = wasp.widgets.Slider(8, 10, 180)
def foreground(self):
wasp.system.bar.clock = True
self._draw()
wasp.system.request_event(wasp.EventMask.TOUCH)
def _draw(self):
draw = wasp.watch.drawable
draw.fill()
wasp.system.bar.draw()
self._checkbox.draw()
draw.string("Intensity:", 10, 85)
self._slider_current.draw()
draw.string("Frequency:", 10, 155)
self._slider_wait_time.draw()
self._draw_preview()
def touch(self, event):
if self._checkbox.touch(event):
if self._checkbox.state:
wasp.watch.hrs.enable()
wasp.watch.hrs.set_hwt(self._slider_wait_time.value)
wasp.watch.hrs.set_drive(self._slider_current.value)
else:
wasp.watch.hrs.disable()
self._checkbox.update()
elif event[2] >= 180:
if self._slider_wait_time.touch(event):
wasp.watch.hrs.set_hwt(self._slider_wait_time.value)
self._slider_wait_time.update()
self._draw_preview()
elif event[2] >= 110:
if self._slider_current.touch(event):
wasp.watch.hrs.set_drive(self._slider_current.value)
self._slider_current.update()
self._draw_preview()
wasp.system.bar.update()
def _draw_preview(self):
"""
Draw a dashed line representing intensity and frequency
with thickness and separation of dashes
"""
draw = wasp.watch.drawable
draw.fill(None, 10, 220, 227, 20)
x = 10
while x < 220:
wasp.watch.drawable.fill(0x27e4, x, 227, 8, (self._slider_current.value + 1) * 3)
x += (8 - self._slider_wait_time.value) * 8

View file

@ -45,8 +45,6 @@ Applications
.. automodule:: apps.alarm .. automodule:: apps.alarm
.. automodule:: Beacon
.. automodule:: apps.calc .. automodule:: apps.calc
.. automodule:: apps.demo .. automodule:: apps.demo

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 568 B

View file

@ -39,8 +39,7 @@ class SettingsApp():
self._yy = wasp.widgets.Spinner(160, 60, 20, 60, 2) self._yy = wasp.widgets.Spinner(160, 60, 20, 60, 2)
self._units = ['Metric', 'Imperial'] self._units = ['Metric', 'Imperial']
self._units_toggle = wasp.widgets.Button(32, 90, 176, 48, "Change") self._units_toggle = wasp.widgets.Button(32, 90, 176, 48, "Change")
self._raise_to_wake_toggle = wasp.widgets.Button(32, 90, 176, 48, "On/Off") self._settings = ['Brightness', 'Notification Level', 'Time', 'Date', 'Units']
self._settings = ['Brightness', 'Notification Level', 'Time', 'Date', 'Units', 'Raise To Wake']
self._sett_index = 0 self._sett_index = 0
self._current_setting = self._settings[0] self._current_setting = self._settings[0]
@ -74,9 +73,6 @@ class SettingsApp():
elif self._current_setting == 'Units': elif self._current_setting == 'Units':
if self._units_toggle.touch(event): if self._units_toggle.touch(event):
wasp.system.units = self._units[(self._units.index(wasp.system.units) + 1) % len(self._units)] wasp.system.units = self._units[(self._units.index(wasp.system.units) + 1) % len(self._units)]
elif self._current_setting == "Raise To Wake":
if self._raise_to_wake_toggle.touch(event):
wasp.system.raise_wake = not wasp.system.raise_wake
self._update() self._update()
def swipe(self, event): def swipe(self, event):
@ -126,8 +122,6 @@ class SettingsApp():
draw.string('DD MM YY',0,180, width=240) draw.string('DD MM YY',0,180, width=240)
elif self._current_setting == 'Units': elif self._current_setting == 'Units':
self._units_toggle.draw() self._units_toggle.draw()
elif self._current_setting == 'Raise To Wake':
self._raise_to_wake_toggle.draw()
self._scroll_indicator.draw() self._scroll_indicator.draw()
self._update() self._update()
mute(False) mute(False)
@ -155,9 +149,3 @@ class SettingsApp():
draw.string(say, 0, 150, width=240) draw.string(say, 0, 150, width=240)
elif self._current_setting == 'Units': elif self._current_setting == 'Units':
draw.string(wasp.system.units, 0, 150, width=240) draw.string(wasp.system.units, 0, 150, width=240)
elif self._current_setting == 'Raise To Wake':
if wasp.system.raise_wake:
say = "On"
else:
say = "Off"
draw.string(say, 0, 150, width=240)

View file

@ -159,12 +159,6 @@ class HRS():
self._i = 0 self._i = 0
self._step = 1 self._step = 1
def read_reg(self, addr):
pass
def write_reg(self, addr, val):
pass
def enable(self): def enable(self):
pass pass
@ -184,12 +178,6 @@ class HRS():
return d return d
def set_drive(self, drive):
pass
def set_hwt(self, t):
pass
backlight = Backlight() backlight = Backlight()
spi = SPI(0) spi = SPI(0)
spi.init(polarity=1, phase=1, baudrate=8000000) spi.init(polarity=1, phase=1, baudrate=8000000)

View file

@ -13,13 +13,10 @@ _I2CADDR = const(0x44)
_ID = const(0x00) _ID = const(0x00)
_ENABLE = const(0x01) _ENABLE = const(0x01)
_ENABLE_HEN = const(0x80) _ENABLE_HEN = const(0x80)
_ENABLE_HWT = const(0x70)
_ENABLE_PDRIVE1 = const(0x08)
_C1DATAM = const(0x08) _C1DATAM = const(0x08)
_C0DATAM = const(0x09) _C0DATAM = const(0x09)
_C0DATAH = const(0x0a) _C0DATAH = const(0x0a)
_PDRIVER = const(0x0c) _PDRIVER = const(0x0c)
_PDRIVER_PDRIVE0 = const(0x40)
_C1DATAH = const(0x0d) _C1DATAH = const(0x0d)
_C1DATAL = const(0x0e) _C1DATAL = const(0x0e)
_C0DATAL = const(0x0f) _C0DATAL = const(0x0f)
@ -91,40 +88,11 @@ class HRS3300:
self.write_reg(_HGAIN, hgain << 2) self.write_reg(_HGAIN, hgain << 2)
def set_drive(self, drive): def set_drive(self, drive):
"""
Set LED drive current
Parameters:
drive (int) LED drive current
0 = 12.5 mA
1 = 20 mA
2 = 30 mA
3 = 40 mA
"""
en = self.read_reg(_ENABLE) en = self.read_reg(_ENABLE)
pd = self.read_reg(_PDRIVER) pd = self.read_reg(_PDRIVER)
en = (en & ~_ENABLE_PDRIVE1 ) | ((drive & 2) << 2) en = (en & 0xf7) | ((drive & 2) << 2)
pd = (pd & ~_PDRIVER_PDRIVE0) | ((drive & 1) << 6) pd = (pd & 0xbf) | ((drive & 1) << 6)
self.write_reg(_ENABLE, en) self.write_reg(_ENABLE, en)
self.write_reg(_PDRIVER, pd) self.write_reg(_PDRIVER, pd)
def set_hwt(self, t):
"""
Set wait time between each conversion cycle
Parameters:
t (int) Wait time between each conversion cycle
0 = 800 ms
1 = 400 ms
2 = 200 ms
3 = 100 ms
4 = 75 ms
5 = 50 ms
6 = 12.5 ms
7 = 0 ms
"""
en = self.read_reg(_ENABLE)
en = (en & ~_ENABLE_HWT) | (t << 4)
self.write_reg(_ENABLE, en)

View file

@ -26,12 +26,6 @@ from apps.launcher import LauncherApp
from apps.pager import PagerApp, CrashApp, NotificationApp from apps.pager import PagerApp, CrashApp, NotificationApp
from apps.steps import StepCounterApp from apps.steps import StepCounterApp
RAISE_WAKE_Y_SWITCH_THRESHOLD = -1536
RAISE_WAKE_SPEED_MODIFIER = 8
RAISE_WAKE_X_THRESHOLD = 512
RAISE_WAKE_Y_THRESHOLD = 0
RAISE_WAKE_REQUIRED_SPEED = 512
class EventType(): class EventType():
"""Enumerated interface actions. """Enumerated interface actions.
@ -120,11 +114,6 @@ class Manager():
self.musicinfo = {} self.musicinfo = {}
self.weatherinfo = {} self.weatherinfo = {}
self.units = "Metric" self.units = "Metric"
self.raise_wake = False
self.raise_wake_last_y = sys.maxsize
self.raise_wake_last_z = sys.maxsize
self.accel_poll_ms = 100
self.accel_poll_expiry = 0
self._theme = ( self._theme = (
b'\x7b\xef' # ble b'\x7b\xef' # ble
@ -177,6 +166,7 @@ class Manager():
def register_defaults(self): def register_defaults(self):
"""Register the default applications.""" """Register the default applications."""
self.register('apps.clock.ClockApp', True, no_except=True) self.register('apps.clock.ClockApp', True, no_except=True)
self.register('apps.steps.StepCounterApp', True, no_except=True)
self.register('apps.stopwatch.StopwatchApp', True, no_except=True) self.register('apps.stopwatch.StopwatchApp', True, no_except=True)
self.register('apps.heart.HeartApp', True, no_except=True) self.register('apps.heart.HeartApp', True, no_except=True)
@ -503,38 +493,6 @@ class Manager():
self._charging != watch.battery.charging(): self._charging != watch.battery.charging():
self.wake() self.wake()
if self.raise_wake:
now = rtc.get_uptime_ms()
if now >= self.accel_poll_expiry:
self.accel_poll_expiry = (now + self.accel_poll_ms)
if self._do_raise_wake():
self.wake()
def _do_raise_wake(self):
(x, y, z) = watch.accel.accel_xyz()
y = -y
if self.raise_wake_last_y == sys.maxsize:
self.raise_wake_last_y = y
self.raise_wake_last_z = z
return False
delta_y = y - self.raise_wake_last_y
delta_z = z - self.raise_wake_last_z
self.raise_wake_last_y = y
self.raise_wake_last_z = z
if y < RAISE_WAKE_Y_SWITCH_THRESHOLD:
return delta_z > RAISE_WAKE_REQUIRED_SPEED
if z > 0:
return delta_y > (RAISE_WAKE_REQUIRED_SPEED + (y - delta_y / 2) / RAISE_WAKE_SPEED_MODIFIER)
return delta_y < (-RAISE_WAKE_REQUIRED_SPEED - (y - delta_y / 2) / RAISE_WAKE_SPEED_MODIFIER)
def run(self, no_except=True): def run(self, no_except=True):
"""Run the system manager synchronously. """Run the system manager synchronously.

View file

@ -430,9 +430,7 @@ class Slider():
v = 0 v = 0
elif v >= self._steps: elif v >= self._steps:
v = self._steps - 1 v = self._steps - 1
changed = self.value != v
self.value = v self.value = v
return changed
class Spinner(): class Spinner():
"""A simple Spinner widget. """A simple Spinner widget.