From a72285eea396b510c6dcef253f7f706953ce9b8b Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Sat, 20 Nov 2021 17:41:34 +0100 Subject: [PATCH] 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