diff options
| -rw-r--r-- | Makefile | 22 | ||||
| -rw-r--r-- | README.rst | 56 | ||||
| -rw-r--r-- | TODO.rst | 2 | ||||
| m--------- | bootloader | 0 | ||||
| -rw-r--r-- | docs/install.rst | 69 | ||||
| m--------- | micropython | 0 | ||||
| m--------- | reloader | 0 | ||||
| -rwxr-xr-x | tools/preprocess.py | 2 | ||||
| -rw-r--r-- | wasp/boards/k9/manifest.py | 45 | ||||
| -rw-r--r-- | wasp/boards/k9/watch.py.in | 139 | ||||
| -rw-r--r-- | wasp/drivers/touch.py | 84 |
11 files changed, 349 insertions, 70 deletions
@@ -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 @@ -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 @@ -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 |
