summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--Makefile7
-rw-r--r--res/feet.pngbin0 -> 388 bytes
-rw-r--r--wasp/apps/steps.py82
-rw-r--r--wasp/boards/pinetime/manifest.py2
-rw-r--r--wasp/boards/pinetime/watch.py.in2
-rw-r--r--wasp/boards/simulator/watch.py23
-rw-r--r--wasp/drivers/bma421.py53
m---------wasp/modules/bma42x-upy0
-rw-r--r--wasp/wasp.py2
10 files changed, 169 insertions, 5 deletions
diff --git a/.gitmodules b/.gitmodules
index 7543a23..ec5319a 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -25,3 +25,6 @@
[submodule "reloader"]
path = reloader
url = https://github.com/daniel-thompson/wasp-reloader
+[submodule "wasp/modules/bma42x-upy"]
+ path = wasp/modules/bma42x-upy
+ url = https://github.com/daniel-thompson/bma42x-upy
diff --git a/Makefile b/Makefile
index 5cdd4df..39fb23e 100644
--- a/Makefile
+++ b/Makefile
@@ -16,10 +16,6 @@ submodules :
bootloader:
$(MAKE) -C bootloader/ BOARD=$(BOARD)_nrf52832 all genhex
- python3 -m nordicsemi dfu genpkg \
- --bootloader bootloader/_build-$(BOARD)_nrf52832/$(BOARD)_nrf52832_bootloader-*-nosd.hex \
- --softdevice bootloader/lib/softdevice/s132_nrf52_6.1.1/s132_nrf52_6.1.1_softdevice.hex \
- bootloader.zip
python3 tools/hexmerge.py \
bootloader/_build-$(BOARD)_nrf52832/$(BOARD)_nrf52832_bootloader-*-nosd.hex \
bootloader/lib/softdevice/s132_nrf52_6.1.1/s132_nrf52_6.1.1_softdevice.hex \
@@ -40,7 +36,8 @@ micropython: wasp/boards/pinetime/watch.py
$(MAKE) -C micropython/ports/nrf \
BOARD=$(BOARD) SD=s132 \
MICROPY_VFS_LFS2=1 \
- FROZEN_MANIFEST=$(PWD)/wasp/boards/$(BOARD)/manifest.py
+ FROZEN_MANIFEST=$(PWD)/wasp/boards/$(BOARD)/manifest.py \
+ USER_C_MODULES=$(PWD)/wasp/modules
python3 -m nordicsemi dfu genpkg \
--dev-type 0x0052 \
--application micropython/ports/nrf/build-$(BOARD)-s132/firmware.hex \
diff --git a/res/feet.png b/res/feet.png
new file mode 100644
index 0000000..03d43d5
--- /dev/null
+++ b/res/feet.png
Binary files differ
diff --git a/wasp/apps/steps.py b/wasp/apps/steps.py
new file mode 100644
index 0000000..d114eff
--- /dev/null
+++ b/wasp/apps/steps.py
@@ -0,0 +1,82 @@
+# SPDX-License-Identifier: LGPL-3.0-or-later
+# Copyright (C) 2020 Daniel Thompson
+
+import wasp
+
+import fonts
+import icons
+import time
+import watch
+
+# 2-bit RLE, generated from res/feet.png, 240 bytes
+feet = (
+ b'\x02'
+ b'00'
+ b'\x13\xc1-\xc4+\xc6*\xc6*\xc6&\xc3\x01\xc6\t\xc2'
+ b'\x1b\xc3\x02\xc5\x08\xc4\x1a\xc4\x01\xc5\x08\xc5\x19\xc4\x02\xc3'
+ b'\x08\xc6\x17\xc1\x02\xc3\x02\xc3\x08\xc6\x16\xc3\x02\xc1\x0e\xc6'
+ b'\x01\xc3\x12\xc3\x11\xc6\x01\xc3\x13\xc2\x05\xc2\n\xc5\x02\xc3'
+ b'\x10\xc2\x01\xc2\x02\xc6\n\xc4\x01\xc4\x10\xc2\x04\xc7\x0b\xc1'
+ b'\x03\xc3\x11\xc3\x02\xc8\x10\xc2\x01\xc3\r\xc2\x02\xc9\x13\xc3'
+ b'\x0b\xc1\x05\xc9\x0c\xc2\x05\xc3\x0b\xc2\x03\xc9\x0c\xc5\x03\xc2'
+ b'\x0c\xc2\x02\xca\x0c\xc6\x05\xc2\t\xc2\x02\xca\x0c\xc7\x03\xc3'
+ b'\r\xca\x0c\xc8\x02\xc3\x0c\xca\r\xc9\x02\xc1\r\xca\r\xc9'
+ b'\x04\xc2\n\xca\x0e\xc9\x02\xc3\n\xca\x0e\xc9\x02\xc2\x0b\xca'
+ b'\x0e\xca\x0e\xca\x0e\xca\x0f\xc9\x0e\xca\x0f\xca\r\xca\x0f\xca'
+ b'\r\xca\x10\xcb\x0b\xca\x10\xcc\n\xca\x10\xcd\t\xca\x11\xcc'
+ b'\x08\xca\x12\xcc\x07\xcb\x13\xcb\x06\xcb\x14\xcb\x05\xcc\x15\xca'
+ b'\x04\xcc\x16\xc9\x05\xcc\x17\xc7\x05\xcd\x17\xc7\x05\xcc\x1a\xc4'
+ b"\x07\xcb%\xca&\xca'\xc8)\xc6+\xc4\x0e"
+)
+
+class StepCounterApp():
+ NAME = 'Steps'
+ ICON = icons.app
+
+ def __init__(self):
+ watch.accel.reset()
+ self._meter = wasp.widgets.BatteryMeter()
+ self._count = 0
+
+ def foreground(self):
+ """Activate the application."""
+ self._last_clock = ( -1, -1, -1, -1, -1, -1 )
+
+ self._draw()
+ wasp.system.request_tick(1000)
+
+ def tick(self, ticks):
+ self._count += 686;
+ self._update()
+
+ def _draw(self):
+ """Draw the display from scratch."""
+ draw = wasp.watch.drawable
+ draw.fill()
+ draw.blit(feet, 12, 132-24)
+
+ self._last_count = -1
+ self._update()
+ self._meter.draw()
+
+ def _update(self):
+ draw = wasp.watch.drawable
+
+ # Lazy update of the clock and battery meter
+ now = wasp.watch.rtc.get_localtime()
+ if now[4] != self._last_clock[4]:
+ t1 = '{:02}:{:02}'.format(now[3], now[4])
+ draw.set_font(fonts.sans24)
+ draw.string(t1, 48, 16, 240-96)
+ self._last_clock = now
+ self._meter.update()
+
+ if now[2] != self._last_clock[2]:
+ watch.accel.steps = 0
+ draw.fill(60, 132-18, 180, 36)
+
+ count = watch.accel.steps
+ t = str(count)
+ w = fonts.width(fonts.sans36, t)
+ draw.set_font(fonts.sans36)
+ draw.string(t, 228-w, 132-18)
diff --git a/wasp/boards/pinetime/manifest.py b/wasp/boards/pinetime/manifest.py
index f7cb9d9..61cc24a 100644
--- a/wasp/boards/pinetime/manifest.py
+++ b/wasp/boards/pinetime/manifest.py
@@ -9,10 +9,12 @@ freeze('../..',
'apps/launcher.py',
'apps/pager.py',
'apps/settings.py',
+ 'apps/steps.py',
'apps/stopwatch.py',
'apps/testapp.py',
'boot.py',
'draw565.py',
+ 'drivers/bma421.py',
'drivers/battery.py',
'drivers/cst816s.py',
'drivers/nrf_rtc.py',
diff --git a/wasp/boards/pinetime/watch.py.in b/wasp/boards/pinetime/watch.py.in
index 46fc6f6..d064d8f 100644
--- a/wasp/boards/pinetime/watch.py.in
+++ b/wasp/boards/pinetime/watch.py.in
@@ -18,6 +18,7 @@ from machine import Pin
from machine import SPI
from drivers.battery import Battery
+from drivers.bma421 import BMA421
from drivers.cst816s import CST816S
from drivers.signal import Signal
from drivers.st7789 import ST7789_SPI
@@ -65,6 +66,7 @@ battery = Battery(
Signal(Pin('USB_PWR', Pin.IN), invert=True))
button = Pin('BUTTON', Pin.IN)
i2c = I2C(1, scl='I2C_SCL', sda='I2C_SDA')
+accel = BMA421(i2c)
touch = CST816S(i2c)
vibrator = Vibrator(Pin('MOTOR', Pin.OUT, value=0), active_low=True)
diff --git a/wasp/boards/simulator/watch.py b/wasp/boards/simulator/watch.py
index 178b1eb..b9de73d 100644
--- a/wasp/boards/simulator/watch.py
+++ b/wasp/boards/simulator/watch.py
@@ -22,6 +22,28 @@ from drivers.cst816s import CST816S
from drivers.st7789 import ST7789_SPI
from drivers.vibrator import Vibrator
+class Accelerometer:
+ """Simulated accelerometer.
+
+ Accelerometers such as BMA421 are complex and most of the driver
+ is written in C. For that reason we simulate the accelerometer
+ rather than emulate (by comparison we emulate the ST7789).
+ """
+ def reset(self):
+ self._steps = 3
+
+ @property
+ def steps(self):
+ """Report the number of steps counted."""
+ if self._steps < 10000:
+ self._steps = int(self._steps * 1.34)
+ else:
+ self._steps += 1
+ return self._steps
+
+ @steps.setter
+ def steps(self, value):
+ self.reset()
class Backlight(object):
def __init__(self, level=1):
@@ -105,6 +127,7 @@ display = ST7789_SPI(240, 240, spi,
res=Pin("DISP_RST", Pin.OUT, quiet=True))
drawable = draw565.Draw565(display)
+accel = Accelerometer()
battery = Battery()
button = Pin('BUTTON', Pin.IN, quiet=True)
rtc = RTC()
diff --git a/wasp/drivers/bma421.py b/wasp/drivers/bma421.py
new file mode 100644
index 0000000..aae4b59
--- /dev/null
+++ b/wasp/drivers/bma421.py
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: LGPL-3.0-or-later
+# Copyright (C) 2020 Daniel Thompson
+
+"""Bosch BMA421 accelerometer driver
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"""
+
+import bma42x
+import time
+
+class BMA421:
+ """BMA421 driver
+
+ .. automethod:: __init__
+ """
+ def __init__(self, i2c):
+ """Configure the driver.
+
+ :param machine.I2C i2c: I2C bus used to access the sensor.
+ """
+ self._dev = bma42x.BMA42X(i2c)
+
+ def reset(self):
+ """Reset and reinitialize the sensor."""
+ dev = self._dev
+
+ # Init, reset, wait for reset, enable I2C watchdog
+ dev.init()
+ dev.set_command_register(0xb6)
+ time.sleep(0.20)
+ dev.set_reg(bma42x.NV_CONFIG_ADDR, 6);
+
+ # Configure the sensor for basic step counting
+ dev.write_config_file()
+ dev.set_accel_enable(True)
+ dev.set_accel_config(odr=bma42x.OUTPUT_DATA_RATE_100HZ,
+ range=bma42x.ACCEL_RANGE_2G,
+ bandwidth=bma42x.ACCEL_NORMAL_AVG4,
+ perf_mode=bma42x.CIC_AVG_MODE)
+ dev.feature_enable(bma42x.STEP_CNTR, True)
+
+ @property
+ def steps(self):
+ """Report the number of steps counted."""
+ return self._dev.step_counter_output()
+
+ @steps.setter
+ def steps(self, value):
+ if value != 0:
+ raise ValueError()
+ # TODO: There is a more efficient way to reset the step counter
+ # but I haven't looked it up yet!
+ self.reset()
diff --git a/wasp/modules/bma42x-upy b/wasp/modules/bma42x-upy
new file mode 160000
+Subproject 55c16a0d0407b1f15efe0d2118a4cca13102fe7
diff --git a/wasp/wasp.py b/wasp/wasp.py
index 8f09a9a..b94bef5 100644
--- a/wasp/wasp.py
+++ b/wasp/wasp.py
@@ -25,6 +25,7 @@ from apps.flashlight import FlashlightApp
from apps.launcher import LauncherApp
from apps.pager import PagerApp, CrashApp
from apps.settings import SettingsApp
+from apps.steps import StepCounterApp
from apps.stopwatch import StopwatchApp
from apps.testapp import TestApp
@@ -108,6 +109,7 @@ class Manager():
# TODO: Eventually these should move to main.py
self.register(ClockApp(), True)
self.register(StopwatchApp(), True)
+ self.register(StepCounterApp(), True)
self.register(FlashlightApp(), False)
self.register(SettingsApp(), False)
self.register(TestApp(), False)