summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile22
-rw-r--r--README.rst56
-rw-r--r--TODO.rst2
m---------bootloader0
-rw-r--r--docs/install.rst69
m---------micropython0
m---------reloader0
-rwxr-xr-xtools/preprocess.py2
-rw-r--r--wasp/boards/k9/manifest.py45
-rw-r--r--wasp/boards/k9/watch.py.in139
-rw-r--r--wasp/drivers/touch.py84
11 files changed, 349 insertions, 70 deletions
diff --git a/Makefile b/Makefile
index df9afcf..c0f29d2 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,8 @@ all : bootloader reloader micropython
ifdef BOARD
WASP_WATCH_PY = wasp/boards/$(BOARD)/watch.py
$(WASP_WATCH_PY) : $(WASP_WATCH_PY).in
- (cd wasp; ../tools/preprocess.py ../$(WASP_WATCH_PY).in > ../$(WASP_WATCH_PY))
+ (cd wasp; ../tools/preprocess.py ../$(WASP_WATCH_PY).in > ../$(WASP_WATCH_PY)) \
+ || ($(RM) $(WASP_WATCH_PY); false)
else
BOARD ?= $(error Please set BOARD=)
endif
@@ -21,28 +22,28 @@ clean :
submodules :
git submodule update --init --recursive
-bootloader:
+bootloader: build-$(BOARD)
$(RM) bootloader/_build-$(BOARD)_nrf52832//$(BOARD)_nrf52832_bootloader-*-nosd.hex
$(MAKE) -C bootloader/ BOARD=$(BOARD)_nrf52832 all genhex
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 \
- -o bootloader.hex
- python3 tools/hex2c.py bootloader.hex > \
+ -o build-$(BOARD)/bootloader.hex
+ python3 tools/hex2c.py build-$(BOARD)/bootloader.hex > \
reloader/src/boards/$(BOARD)/bootloader.h
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-daflasher.zip
+ build-$(BOARD)/bootloader-daflasher.zip
-reloader: bootloader
+reloader: bootloader build-$(BOARD)
$(MAKE) -C reloader/ BOARD=$(BOARD)
- mv reloader/build-$(BOARD)/reloader.zip .
+ mv reloader/build-$(BOARD)/reloader.zip build-$(BOARD)/
softdevice:
micropython/ports/nrf/drivers/bluetooth/download_ble_stack.sh
-micropython: $(WASP_WATCH_PY)
+micropython: $(WASP_WATCH_PY) build-$(BOARD)
$(MAKE) -C micropython/mpy-cross
$(RM) micropython/ports/nrf/build-$(BOARD)-s132/frozen_content.c
$(MAKE) -C micropython/ports/nrf \
@@ -53,7 +54,10 @@ micropython: $(WASP_WATCH_PY)
python3 -m nordicsemi dfu genpkg \
--dev-type 0x0052 \
--application micropython/ports/nrf/build-$(BOARD)-s132/firmware.hex \
- micropython.zip
+ build-$(BOARD)/micropython.zip
+
+build-$(BOARD):
+ mkdir -p $@
dfu:
python3 -m nordicsemi dfu serial --package micropython.zip --port /dev/ttyACM0
diff --git a/README.rst b/README.rst
index 08a3253..5024ad2 100644
--- a/README.rst
+++ b/README.rst
@@ -61,60 +61,6 @@ which includes a detailed `Applicaiton Writer's Guide
<https://wasp-os.readthedocs.io/en/latest/appguide.html>`_ to help you
get started coding for wasp-os as quickly as possible.
-Building from source
---------------------
-
-Building wasp-os and launching the wasp-os simulator requires Python 3.6
-(or later) and the following python modules: click, numpy, pexpect, PIL
-(or Pillow), pyserial, pysdl2.
-
-On Debian Buster the required python modules can be obtained using the
-following commands:
-
-.. code-block:: sh
-
- sudo apt install \
- git build-essential libsdl2-2.0.0 \
- python3-click python3-numpy python3-pexpect \
- python3-pil python3-pip python3-serial
- pip3 install --user pysdl2
-
-You will also need a toolchain for the Arm Cortex-M4. wasp-os is developed and
-tested using the `GNU-RM toolchain
-<https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm>`_
-(9-2019-q4) from Arm.
-
-.. note::
-
- There are known problems with toolchains older than gcc-7.3 when
- link time optimization is enabled during the MicroPython build
- (and LTO is enabled by default).
-
-Get the code from
-`https://github.com/daniel-thompson/wasp-os <https://github.com/daniel-thompson/wasp-os>`_ :
-
-.. code-block:: sh
-
- git clone https://github.com/daniel-thompson/wasp-os
- cd wasp-os
- make submodules
- make softdevice
-
-Build the firmware:
-
-.. code-block:: sh
-
- make -j `nproc` BOARD=pinetime all
-
-Finally to test out ideas and concepts on the simulator try:
-
-.. code-block:: sh
-
- make sim
-
-See :ref:`Testing on the simulator` for more details on how
-to use the simulator.
-
Getting Started
---------------
@@ -126,7 +72,7 @@ devices:
The
`Installation Guide <https://wasp-os.readthedocs.io/en/latest/install.html>`_
-contains detailed instructions on how to install wasp-os.
+contains detailed instructions on how to build and install wasp-os.
At the end of the install process your watch will show the time (03:00)
together with a date and battery meter. When the watch goes into power
diff --git a/TODO.rst b/TODO.rst
index ec0ca7a..8efe6b3 100644
--- a/TODO.rst
+++ b/TODO.rst
@@ -46,7 +46,7 @@ Wasp-os
* [X] Implement simple RTC for nrf52
0.2 (a.k.a. M2): Great developer experience
-------------------------------
+-------------------------------------------
The focus for M2 is to make development faster and easier by providing
a file system and file transfer code. This allows much faster
diff --git a/bootloader b/bootloader
-Subproject 89ba9a874fa052ae7b0df8a9b6a6f8916309cd2
+Subproject 91fad65a8a0c5b3be0468e914a5788a519591c5
diff --git a/docs/install.rst b/docs/install.rst
index 8c3ed32..eb3e9fe 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -65,6 +65,63 @@ display with touch screen, a step counter and a heart rate sensor.
Both the wasp-bootloader and the main OS image can be installed onto a
P8 using DaFlasher for Android. No tools are required.
+.. _Building wasp-os from source:
+
+Building wasp-os from source
+----------------------------
+
+
+Building wasp-os and launching the wasp-os simulator requires Python 3.6
+(or later) and the following python modules: click, numpy, pexpect, PIL
+(or Pillow), pyserial, pysdl2.
+
+On Debian Buster the required python modules can be obtained using the
+following commands:
+
+.. code-block:: sh
+
+ sudo apt install \
+ git build-essential libsdl2-2.0.0 \
+ python3-click python3-numpy python3-pexpect \
+ python3-pil python3-pip python3-serial
+ pip3 install --user pysdl2
+
+You will also need a toolchain for the Arm Cortex-M4. wasp-os is developed and
+tested using the `GNU-RM toolchain
+<https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm>`_
+(9-2019-q4) from Arm.
+
+.. note::
+
+ There are known problems with toolchains older than gcc-7.3 when
+ link time optimization is enabled during the MicroPython build
+ (and LTO is enabled by default).
+
+Get the code from
+`https://github.com/daniel-thompson/wasp-os <https://github.com/daniel-thompson/wasp-os>`_ :
+
+.. code-block:: sh
+
+ git clone https://github.com/daniel-thompson/wasp-os
+ cd wasp-os
+ make submodules
+ make softdevice
+
+Build the firmware:
+
+.. code-block:: sh
+
+ make -j `nproc` BOARD=pinetime all
+
+Finally to test out ideas and concepts on the simulator try:
+
+.. code-block:: sh
+
+ make sim
+
+See :ref:`Testing on the simulator` for more details on how
+to use the simulator.
+
Installing wasp-bootloader
--------------------------
@@ -78,7 +135,8 @@ To install the bootloader using DaFlasher for Android:
and copy the DaFlasher bootloaders to your Android device. You will need
`DaFitBootloader23Hacked.bin <https://github.com/atc1441/DaFlasherFiles/blob/master/DaFitBootloader23Hacked.bin>`_ and
`FitBootloaderDFU2.0.1.zip <https://github.com/atc1441/DaFlasherFiles/blob/master/FitBootloaderDFU2.0.1.zip>`_.
-* Copy ``bootloader-daflasher.zip`` to your Android device.
+* Copy ``bootloader-daflasher.zip`` (see :ref:`Building wasp-os from source`
+ above) to your Android device.
* Open the app and connect to the device (e.g. *Y7S* if you have a developer
edition PineTime).
* Read the disclaimer carefully, then click **Ok**.
@@ -160,7 +218,8 @@ DaFlasher for Android
To install the main firmware using DaFlasher for Android:
-* Copy ``micropython.zip`` to your Android device and download
+* Copy ``micropython.zip`` (see :ref:`Building wasp-os from source`) to
+ your Android device and download
`DaFlasher <https://play.google.com/store/apps/details?id=com.atcnetz.paatc.patc>`_
if you do not already have it.
* Open the app and connect to the device (e.g. *PineDFU* if you have a
@@ -175,7 +234,8 @@ nRF Connect for Android
To install the main firmware using nRF Connect for Android:
-* Copy ``micropython.zip`` to your Android device and download
+* Copy ``micropython.zip`` (see :ref:`Building wasp-os from source`) to
+ your Android device and download
`nRF Connect <https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp>`_
for Android if you do not already have it.
* Connect to the device (e.g. *PineDFU* if you have a PineTime) using
@@ -189,5 +249,6 @@ wasptool for GNU/Linux
To install the main firmware from a GNU/Linux workstation:
* Look up the MAC address for your watch (try: ``sudo hcitool lescan``\ ).
-* Use ota-dfu to upload ``micropython.zip`` to the device. For example:
+* Use ota-dfu to upload ``micropython.zip`` (see
+ :ref:`Building wasp-os from source`) to the device. For example:
``tools/ota-dfu/dfu.py -z micropython.zip -a A0:B1:C2:D3:E3:F5 --legacy``
diff --git a/micropython b/micropython
-Subproject c7cf47a3681ab1625b52b7b8663bfa95dd5d909
+Subproject 6df2db3f4cbe046eac17d7893d66a6c07722840
diff --git a/reloader b/reloader
-Subproject b4512e5d92d062a65a216d68bffcdc03ff1625c
+Subproject 9f55c66be8f129fd00e3eda60988b4cbeffd884
diff --git a/tools/preprocess.py b/tools/preprocess.py
index 4c43c2a..0cd3bdf 100755
--- a/tools/preprocess.py
+++ b/tools/preprocess.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020 Daniel Thompson
diff --git a/wasp/boards/k9/manifest.py b/wasp/boards/k9/manifest.py
new file mode 100644
index 0000000..1c1d7e2
--- /dev/null
+++ b/wasp/boards/k9/manifest.py
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: LGPL-3.0-or-later
+# Copyright (C) 2020 Daniel Thompson
+
+freeze('.', 'watch.py', opt=3)
+freeze('../..',
+ (
+ 'apps/clock.py',
+ 'apps/flashlight.py',
+ 'apps/heart.py',
+ '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/hrs3300.py',
+ 'drivers/nrf_rtc.py',
+ 'drivers/signal.py',
+ 'drivers/st7789.py',
+ 'drivers/touch.py',
+ 'drivers/vibrator.py',
+ 'fonts/__init__.py',
+ 'fonts/clock.py',
+ 'fonts/sans24.py',
+ 'fonts/sans28.py',
+ 'fonts/sans36.py',
+ 'gadgetbridge.py',
+ 'icons.py',
+ 'ppg.py',
+ 'shell.py',
+ 'wasp.py',
+ 'widgets.py',
+ ),
+ opt=3
+)
+freeze('../../drivers/flash',
+ (
+ 'bdevice.py',
+ 'flash/flash_spi.py'
+ ), opt=3
+)
diff --git a/wasp/boards/k9/watch.py.in b/wasp/boards/k9/watch.py.in
new file mode 100644
index 0000000..5126a87
--- /dev/null
+++ b/wasp/boards/k9/watch.py.in
@@ -0,0 +1,139 @@
+# SPDX-License-Identifier: LGPL-3.0-or-later
+# Copyright (C) 2020 Daniel Thompson
+
+def nop():
+ pass
+schedule = nop
+def _callback(obj):
+ schedule()
+
+# Start measuring time (and feeding the watchdog) before *anything* else
+from machine import RTCounter
+from drivers.nrf_rtc import RTC
+rtc = RTC(RTCounter(1, mode=RTCounter.PERIODIC, period=1, callback=_callback))
+rtc.counter.start()
+
+import os
+import time
+
+import draw565
+
+from machine import I2C
+from machine import Pin
+#from machine import Signal
+from machine import SPI
+
+from drivers.battery import Battery
+from drivers.bma421 import BMA421
+from drivers.touch import TouchButton
+from drivers.hrs3300 import HRS3300
+from drivers.signal import Signal
+from drivers.st7789 import ST7789_SPI
+from drivers.vibrator import Vibrator
+from flash.flash_spi import FLASH
+
+from ubluepy import uart_connected as connected
+
+class Backlight(object):
+ lo = Pin("BL_LO", Pin.OUT, value=0)
+ mid = Pin("BL_MID", Pin.OUT, value=1)
+ hi = Pin("BL_HI", Pin.OUT, value=1)
+
+ def __init__(self, level=1):
+ self.set(level)
+
+ def set(self, level):
+ hi = 1
+ mid = 1
+ lo = 0
+
+ if level >= 3:
+ hi = 0
+ mid = 0
+ elif level == 2:
+ hi = 0
+ elif level == 1:
+ mid = 0
+
+ self.hi(hi)
+ self.mid(mid)
+ self.lo(lo)
+
+# Setup the display (and manage the backlight)
+backlight = Backlight(0)
+spi = SPI(0)
+spi.init(polarity=1, phase=1, baudrate=8000000)
+display = ST7789_SPI(240, 240, spi,
+ cs=Pin("DISP_CS", Pin.OUT),
+ dc=Pin("DISP_DC", Pin.OUT),
+ res=Pin("DISP_RST", Pin.OUT))
+drawable = draw565.Draw565(display)
+
+def boot_msg(s):
+ drawable.string(s, 0, 108, width=240)
+ if safe_mode:
+ time.sleep_ms(500)
+
+safe_mode = True
+boot_msg("Init button")
+button = Pin('BUTTON', Pin.IN)
+safe_mode = button.value()
+if safe_mode:
+ backlight.set(2)
+ time.sleep(1)
+
+try:
+ # Setup the last few bits and pieces
+ boot_msg("Init battery")
+ battery = Battery(
+ Pin('BATTERY', Pin.IN),
+ Signal(Pin('CHARGING', Pin.IN), invert=True),
+ Signal(Pin('USB_PWR', Pin.IN), invert=True))
+ boot_msg("Init I2C")
+ i2c = I2C(1, scl='I2C_SCL', sda='I2C_SDA')
+ boot_msg("Init BMA421")
+ accel = BMA421(i2c)
+ boot_msg("Init HRS3300")
+ hrs = HRS3300(i2c)
+ boot_msg("Init touch")
+ touch = TouchButton(Pin('TP_INT', Pin.IN),
+ Pin('TP_RST', Pin.OUT, value=0), _callback)
+ boot_msg("Init motor")
+ vibrator = Vibrator(Pin('MOTOR', Pin.OUT, value=0), active_low=True)
+
+ # Release flash from deep power-down
+ boot_msg("Wake SPINOR")
+ nor_cs = Pin('NOR_CS', Pin.OUT, value=1)
+ nor_cs(0)
+ spi.write('\xAB')
+ nor_cs(1)
+
+ # Mount the filesystem
+ boot_msg("Init SPINOR")
+ flash = FLASH(spi, (nor_cs,))
+ try:
+ boot_msg("Mount FS")
+ os.mount(flash, '/flash')
+ except AttributeError:
+ # Format the filesystem (and provide a default version of main.py)
+ boot_msg("Format FS")
+ os.VfsLfs2.mkfs(flash)
+ boot_msg("Retry mount FS")
+ os.mount(flash,'/flash')
+ boot_msg("Write main.py")
+ with open('/flash/main.py', 'w') as f:
+ f.write('''\
+#include('main.py')
+''')
+
+ # Only change directory if the button is not pressed (this will
+ # allow us access to fix any problems with main.py)!
+ if not safe_mode:
+ boot_msg("Enter /flash")
+ os.chdir('/flash')
+ boot_msg("Run main.py")
+ else:
+ boot_msg("Safe mode")
+except:
+ drawable.string("FAILED", 0, 136, width=240)
+ backlight.set(2)
diff --git a/wasp/drivers/touch.py b/wasp/drivers/touch.py
new file mode 100644
index 0000000..0b08653
--- /dev/null
+++ b/wasp/drivers/touch.py
@@ -0,0 +1,84 @@
+# SPDX-License-Identifier: LGPL-3.0-or-later
+# Copyright (C) 2020 Daniel Thompson
+
+"""Basic touch sensor driver
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"""
+
+import array
+import time
+from machine import Pin
+from watch import rtc
+
+class TouchButton:
+ """Simple touch controller driver.
+
+ .. automethod:: __init__
+ """
+
+ def __init__(self, intr, rst, schedule=None):
+ """Specify the bus used by the touch controller.
+
+ :param machine.I2C bus: I2C bus for the CST816S.
+ """
+ self.tp_int = intr
+ self.tp_rst = rst
+ self.schedule = schedule
+ self.event = array.array('H', (0, 0, 0))
+
+ self._reset()
+ self.tp_int.irq(trigger=Pin.IRQ_FALLING, handler=self.get_touch_data)
+
+ def _reset(self):
+ self.tp_rst.off()
+ time.sleep_ms(5)
+ self.tp_rst.on()
+ time.sleep_ms(50)
+ self.event[0] = 0
+ self._wake_at = rtc.get_uptime_ms() + 300
+
+ def get_touch_data(self, pin_obj):
+ """Synthesize a right swipe during interrupt.
+ """
+ self.event[0] = 4
+
+ if self.schedule:
+ self.schedule(self)
+
+ def get_event(self):
+ """Receive a touch event.
+
+ Check for a pending touch event and, if an event is pending,
+ prepare it ready to go in the event queue.
+
+ :return: An event record if an event is received, None otherwise.
+ """
+ if rtc.get_uptime_ms() < self._wake_at:
+ self.event[0] = 0
+
+ if self.event[0] == 0:
+ return None
+
+ return self.event
+
+ def reset_touch_data(self):
+ """Reset touch data.
+
+ Reset touch data, call this function after processing an event.
+ """
+ self.event[0] = 0
+
+ def wake(self):
+ """Wake up touch controller chip.
+
+ Just reset the chip in order to wake it up
+ """
+ self._reset()
+
+ def sleep(self):
+ """Put touch controller chip on sleep mode to save power.
+ """
+ self.tp_rst.off()
+
+ # Ensure get_event() cannot return anything
+ self.event[0] = 0