From 9a1964ce418e7447768a370e682303fd9a61eaa4 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Sat, 20 Nov 2021 17:39:46 +0100 Subject: [PATCH 1/9] Add hrs3300 write_reg and read_reg to simulator Signed-off-by: Francesco Gazzetta --- wasp/boards/simulator/watch.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wasp/boards/simulator/watch.py b/wasp/boards/simulator/watch.py index e5cf2b2..f6e3d9f 100644 --- a/wasp/boards/simulator/watch.py +++ b/wasp/boards/simulator/watch.py @@ -155,6 +155,12 @@ class HRS(): self._i = 0 self._step = 1 + def read_reg(self, addr): + pass + + def write_reg(self, addr, val): + pass + def enable(self): pass From fd5d6cbbe8e873856567583bcd61601b66459c40 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Sat, 20 Nov 2021 17:40:52 +0100 Subject: [PATCH 2/9] Make Slider.touch return True when the value changed Signed-off-by: Francesco Gazzetta --- wasp/widgets.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wasp/widgets.py b/wasp/widgets.py index 556c7f5..9d80502 100644 --- a/wasp/widgets.py +++ b/wasp/widgets.py @@ -430,7 +430,9 @@ class Slider(): v = 0 elif v >= self._steps: v = self._steps - 1 + changed = self.value != v self.value = v + return changed class Spinner(): """A simple Spinner widget. From a72285eea396b510c6dcef253f7f706953ce9b8b Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Sat, 20 Nov 2021 17:41:34 +0100 Subject: [PATCH 3/9] Add beacon app Signed-off-by: Francesco Gazzetta --- README.rst | 4 ++ apps/Beacon.py | 130 ++++++++++++++++++++++++++++++++++++++++++++ docs/apps.rst | 2 + res/BeaconApp.png | Bin 0 -> 7000 bytes res/beacon_icon.png | Bin 0 -> 568 bytes 5 files changed, 136 insertions(+) create mode 100644 apps/Beacon.py create mode 100644 res/BeaconApp.png create mode 100644 res/beacon_icon.png diff --git a/README.rst b/README.rst index 6d80324..347d152 100644 --- a/README.rst +++ b/README.rst @@ -257,3 +257,7 @@ application (and the "blank" white screen is a torch application): .. image:: res/WordClkApp.png :alt: Shows a time as words in the wasp-os simulator :width: 179 + +.. image:: res/BeaconApp.png + :alt: Flash the relatively powerful HRS LED repeatedly + :width: 179 diff --git a/apps/Beacon.py b/apps/Beacon.py new file mode 100644 index 0000000..7676fff --- /dev/null +++ b/apps/Beacon.py @@ -0,0 +1,130 @@ +# 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 + +_ENABLE = const(0x01) +_PDRIVER = const(0x0c) + +_ENABLE_HEN = const(0x80) +_ENABLE_PDRIVE1 = const(0x08) +_PDRIVER_PDRIVE0 = const(0x40) +_ENABLE_HWT = const(0x70) + +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) + self._reg_enable = 0x00 # off, 800ms, part of 12.5mA + self._reg_pdriver = 0x2e #0x4e # part of 12.5mA, PON=1, magic + + 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._update() + + def touch(self, event): + updated = self._checkbox.touch(event) + if event[2] >= 180: + updated |= self._slider_wait_time.touch(event) + elif event[2] >= 110: + updated |= self._slider_current.touch(event) + self._update() + if updated: + if self._checkbox.state: + self._enable_led() + else: + self._disable_led() + + def _update(self): + wasp.system.bar.update() + self._checkbox.update() + self._slider_current.update() + self._slider_wait_time.update() + + # 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 + + def _enable_led(self): + self._reg_enable |= _ENABLE_HEN + if self._slider_current.value % 2: + self._reg_pdriver |= _PDRIVER_PDRIVE0 + else: + self._reg_pdriver &= ~_PDRIVER_PDRIVE0 + if self._slider_current.value >> 1: + self._reg_enable |= _ENABLE_PDRIVE1 + else: + self._reg_enable &= ~_ENABLE_PDRIVE1 + self._reg_enable = (self._reg_enable & (~_ENABLE_HWT)) | (self._slider_wait_time.value << 4) + wasp.watch.hrs.write_reg(_PDRIVER, self._reg_pdriver) + #print("writing PDRIVER={:08b}".format(self._reg_pdriver)) + wasp.watch.hrs.write_reg(_ENABLE, self._reg_enable) + #print("writing ENABLE={:08b}".format(self._reg_enable)) + + def _disable_led(self): + self._reg_enable &= ~_ENABLE_HEN + wasp.watch.hrs.write_reg(_ENABLE, self._reg_enable) + #print("writing ENABLE={:08b}".format(self._reg_enable)) diff --git a/docs/apps.rst b/docs/apps.rst index 0ee4272..75140bc 100644 --- a/docs/apps.rst +++ b/docs/apps.rst @@ -45,6 +45,8 @@ Applications .. automodule:: apps.alarm +.. automodule:: Beacon + .. automodule:: apps.calc .. automodule:: apps.demo diff --git a/res/BeaconApp.png b/res/BeaconApp.png new file mode 100644 index 0000000000000000000000000000000000000000..8fc475496a7d7501a31482bb011345b4dc4dc6e8 GIT binary patch literal 7000 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 literal 0 HcmV?d00001 diff --git a/res/beacon_icon.png b/res/beacon_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4bd99f9ab3b4f54abfe38ef8ac800d3fb6e687d9 GIT binary patch literal 568 zcmeAS@N?(olHy`uVBq!ia0vp^2|(Y$410KaHVSAfwcz|4J&$NPH%eizxAJWs?lVR&Hhnq!|i6=oX#o1 z|AO;MA4`K~RKxDsyB9Ct*ya9(CFn)-zbczqGb4+C?|W@^q34oiL}L4f-TztYd@gT0 z>Zzf{dY60O%~JO%(LfVhS%;r zU~S=8<5j->oy_)Cf1m6>$iDuArN!z6a~hR+ehKt61Zd4j(rS48c)?kNYkNPME$Yz9 z@cdyd41^fmm=1U_NMtdtRL$_` zT&l6PLF&OC!QB(HzZ&h=Y|KA)_QSVNdtQBiFF$`~+9qBv#{?Ayp0y0+@pJ3Wtkdk- zDYQs5fE#8ACxbF$f(GjoEywB^-hrp$E`%LSdc%3~Thp~I3!Pc+3oA7kv0iNf+grkP zEza5RV3n<>`T{c*h8~1t0=_nV(-NLpBPQAc!qL$Z^_4Zel x-i9ckpb39c^>Wr}?S@i}TNjD206kN~Tq2R-WwXXr8JHp%JYD@<);T3K0RX)K=cfPw literal 0 HcmV?d00001 From 0cca03a94b0b397276a68b12f683221a51038ce7 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Sat, 28 May 2022 16:12:40 +0200 Subject: [PATCH 4/9] Use functions from driver in beacon app Instead of setting registers from the app. * add wasp.drivers.hrs3300.set_hwt() Signed-off-by: Francesco Gazzetta --- apps/Beacon.py | 70 +++++++++++----------------------- wasp/boards/simulator/watch.py | 6 +++ wasp/drivers/hrs3300.py | 20 ++++++++++ 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/apps/Beacon.py b/apps/Beacon.py index 7676fff..d8423cf 100644 --- a/apps/Beacon.py +++ b/apps/Beacon.py @@ -19,14 +19,6 @@ import wasp import machine from micropython import const -_ENABLE = const(0x01) -_PDRIVER = const(0x0c) - -_ENABLE_HEN = const(0x80) -_ENABLE_PDRIVE1 = const(0x08) -_PDRIVER_PDRIVE0 = const(0x40) -_ENABLE_HWT = const(0x70) - class BeaconApp(): NAME = "Beacon" # 2-bit RLE, 96x64, generated from res/beacon_icon.png, 336 bytes @@ -61,8 +53,6 @@ class BeaconApp(): 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) - self._reg_enable = 0x00 # off, 800ms, part of 12.5mA - self._reg_pdriver = 0x2e #0x4e # part of 12.5mA, PON=1, magic def foreground(self): wasp.system.bar.clock = True @@ -78,53 +68,37 @@ class BeaconApp(): self._slider_current.draw() draw.string("Frequency:", 10, 155) self._slider_wait_time.draw() - self._update() + self._draw_preview() def touch(self, event): - updated = self._checkbox.touch(event) - if event[2] >= 180: - updated |= self._slider_wait_time.touch(event) - elif event[2] >= 110: - updated |= self._slider_current.touch(event) - self._update() - if updated: + if self._checkbox.touch(event): if self._checkbox.state: - self._enable_led() + wasp.watch.hrs.enable() + wasp.watch.hrs.set_hwt(self._slider_wait_time.value) + wasp.watch.hrs.set_drive(self._slider_current.value) else: - self._disable_led() - - def _update(self): + 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() - self._checkbox.update() - self._slider_current.update() - self._slider_wait_time.update() - # Draw a dashed line representing intensity and frequency - # with thickness and separation of dashes + 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 - - def _enable_led(self): - self._reg_enable |= _ENABLE_HEN - if self._slider_current.value % 2: - self._reg_pdriver |= _PDRIVER_PDRIVE0 - else: - self._reg_pdriver &= ~_PDRIVER_PDRIVE0 - if self._slider_current.value >> 1: - self._reg_enable |= _ENABLE_PDRIVE1 - else: - self._reg_enable &= ~_ENABLE_PDRIVE1 - self._reg_enable = (self._reg_enable & (~_ENABLE_HWT)) | (self._slider_wait_time.value << 4) - wasp.watch.hrs.write_reg(_PDRIVER, self._reg_pdriver) - #print("writing PDRIVER={:08b}".format(self._reg_pdriver)) - wasp.watch.hrs.write_reg(_ENABLE, self._reg_enable) - #print("writing ENABLE={:08b}".format(self._reg_enable)) - - def _disable_led(self): - self._reg_enable &= ~_ENABLE_HEN - wasp.watch.hrs.write_reg(_ENABLE, self._reg_enable) - #print("writing ENABLE={:08b}".format(self._reg_enable)) diff --git a/wasp/boards/simulator/watch.py b/wasp/boards/simulator/watch.py index f6e3d9f..7afc61a 100644 --- a/wasp/boards/simulator/watch.py +++ b/wasp/boards/simulator/watch.py @@ -180,6 +180,12 @@ class HRS(): return d + def set_drive(self, drive): + pass + + def set_hwt(self, t): + pass + backlight = Backlight() spi = SPI(0) spi.init(polarity=1, phase=1, baudrate=8000000) diff --git a/wasp/drivers/hrs3300.py b/wasp/drivers/hrs3300.py index 80c8df0..ba05a4b 100644 --- a/wasp/drivers/hrs3300.py +++ b/wasp/drivers/hrs3300.py @@ -13,6 +13,7 @@ _I2CADDR = const(0x44) _ID = const(0x00) _ENABLE = const(0x01) _ENABLE_HEN = const(0x80) +_ENABLE_HWT = const(0x70) _C1DATAM = const(0x08) _C0DATAM = const(0x09) _C0DATAH = const(0x0a) @@ -96,3 +97,22 @@ class HRS3300: self.write_reg(_ENABLE, en) 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) From 4d4c83e8514d9066295ea0a149f11dbdece75fe1 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Sat, 28 May 2022 16:14:36 +0200 Subject: [PATCH 5/9] Docs and constants for hrs3300.set_drive() Signed-off-by: Francesco Gazzetta --- wasp/drivers/hrs3300.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/wasp/drivers/hrs3300.py b/wasp/drivers/hrs3300.py index ba05a4b..c6027c4 100644 --- a/wasp/drivers/hrs3300.py +++ b/wasp/drivers/hrs3300.py @@ -14,10 +14,12 @@ _ID = const(0x00) _ENABLE = const(0x01) _ENABLE_HEN = const(0x80) _ENABLE_HWT = const(0x70) +_ENABLE_PDRIVE1 = const(0x08) _C1DATAM = const(0x08) _C0DATAM = const(0x09) _C0DATAH = const(0x0a) _PDRIVER = const(0x0c) +_PDRIVER_PDRIVE0 = const(0x40) _C1DATAH = const(0x0d) _C1DATAL = const(0x0e) _C0DATAL = const(0x0f) @@ -89,11 +91,21 @@ class HRS3300: self.write_reg(_HGAIN, hgain << 2) 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) pd = self.read_reg(_PDRIVER) - en = (en & 0xf7) | ((drive & 2) << 2) - pd = (pd & 0xbf) | ((drive & 1) << 6) + en = (en & ~_ENABLE_PDRIVE1 ) | ((drive & 2) << 2) + pd = (pd & ~_PDRIVER_PDRIVE0) | ((drive & 1) << 6) self.write_reg(_ENABLE, en) self.write_reg(_PDRIVER, pd) From 5a6dd6124b27d54948ac67eeb191c92687b99d12 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Tue, 14 Jun 2022 15:39:40 -0400 Subject: [PATCH 6/9] Add env/ to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 952b95e..9c81e25 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ attic/ wasp/boards/*/watch.py .idea .vscode +env/ From 244230bad9c207856430c2f818b31a626baca743 Mon Sep 17 00:00:00 2001 From: Ashley Eastwood Date: Tue, 14 Jun 2022 20:06:57 +0100 Subject: [PATCH 7/9] Add a Raise To Wake feature This commit adds a setting (off by default) that allows the watch to wake up when the user raises it to look at the screen. This functionality has mostly been translated from the way that infinitime implements the feature. Tested and developed on the Pinetime. Signed-off-by: Ashley Eastwood --- wasp/apps/settings.py | 14 +++++++++++++- wasp/wasp.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/wasp/apps/settings.py b/wasp/apps/settings.py index 7afd7ef..d4c1425 100644 --- a/wasp/apps/settings.py +++ b/wasp/apps/settings.py @@ -39,7 +39,8 @@ class SettingsApp(): self._yy = wasp.widgets.Spinner(160, 60, 20, 60, 2) self._units = ['Metric', 'Imperial'] self._units_toggle = wasp.widgets.Button(32, 90, 176, 48, "Change") - self._settings = ['Brightness', 'Notification Level', 'Time', 'Date', 'Units'] + self._raise_to_wake_toggle = wasp.widgets.Button(32, 90, 176, 48, "On/Off") + self._settings = ['Brightness', 'Notification Level', 'Time', 'Date', 'Units', 'Raise To Wake'] self._sett_index = 0 self._current_setting = self._settings[0] @@ -73,6 +74,9 @@ class SettingsApp(): elif self._current_setting == 'Units': if self._units_toggle.touch(event): 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() def swipe(self, event): @@ -122,6 +126,8 @@ class SettingsApp(): draw.string('DD MM YY',0,180, width=240) elif self._current_setting == 'Units': self._units_toggle.draw() + elif self._current_setting == 'Raise To Wake': + self._raise_to_wake_toggle.draw() self._scroll_indicator.draw() self._update() mute(False) @@ -149,3 +155,9 @@ class SettingsApp(): draw.string(say, 0, 150, width=240) elif self._current_setting == 'Units': 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) diff --git a/wasp/wasp.py b/wasp/wasp.py index 2dca1f1..64bd322 100644 --- a/wasp/wasp.py +++ b/wasp/wasp.py @@ -114,6 +114,10 @@ class Manager(): self.musicinfo = {} self.weatherinfo = {} self.units = "Metric" + self.raise_wake = False + self.last_raise_y = 0 + self.accel_poll_ms = 100 + self.accel_poll_expiry = 0 self._theme = ( b'\x7b\xef' # ble @@ -493,6 +497,37 @@ class Manager(): self._charging != watch.battery.charging(): 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 (x + 335) <= 670 and z < 0: + if self.sleep_at: + if y <= 0: + return False + else: + self.last_raise_y = 0 + return False + + if y >= 0: + self.last_raise_y = 0 + return False + + if y + 230 < self.last_raise_y: + self.last_raise_y = y + return True + + return False + def run(self, no_except=True): """Run the system manager synchronously. From bb8f651481b1c0ea96898936a88472c84f3cefb7 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Tue, 14 Jun 2022 18:36:07 -0400 Subject: [PATCH 8/9] Improve raise-to-wake algorithm From , with constants tuned a bit for my personal preference. --- wasp/wasp.py | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/wasp/wasp.py b/wasp/wasp.py index 64bd322..187dd56 100644 --- a/wasp/wasp.py +++ b/wasp/wasp.py @@ -26,6 +26,12 @@ from apps.launcher import LauncherApp from apps.pager import PagerApp, CrashApp, NotificationApp 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(): """Enumerated interface actions. @@ -115,7 +121,8 @@ class Manager(): self.weatherinfo = {} self.units = "Metric" self.raise_wake = False - self.last_raise_y = 0 + self.raise_wake_last_y = sys.maxsize + self.raise_wake_last_z = sys.maxsize self.accel_poll_ms = 100 self.accel_poll_expiry = 0 @@ -510,23 +517,24 @@ class Manager(): y = -y - if (x + 335) <= 670 and z < 0: - if self.sleep_at: - if y <= 0: - return False - else: - self.last_raise_y = 0 - return False - - if y >= 0: - self.last_raise_y = 0 - return False - - if y + 230 < self.last_raise_y: - self.last_raise_y = y - return True - + 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): """Run the system manager synchronously. From f4ad9fb4cd00dee27b925b9b7d4536b0ec160612 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Tue, 14 Jun 2022 18:37:23 -0400 Subject: [PATCH 9/9] Disable the step counter app Why do I need this :D --- wasp/wasp.py | 1 - 1 file changed, 1 deletion(-) diff --git a/wasp/wasp.py b/wasp/wasp.py index 187dd56..2497957 100644 --- a/wasp/wasp.py +++ b/wasp/wasp.py @@ -177,7 +177,6 @@ class Manager(): def register_defaults(self): """Register the default applications.""" 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.heart.HeartApp', True, no_except=True)