Skip to content

Using Adafruit CircuitPython

Papyr doesn't come pre-installed with CircuitPython , but support was recently added to it in CircuitPython repo, and Adafruit NRF52 Bootloader.

Please note that CircuitPython is not current optimized, we have not performed any current measurement or optimizations on it.

NOTE: Whenever you need to disconnect Papyr from USB, then you need to 'eject'/'safely remove' the storage device ("CIRCUITPY") first, like a normal USB pen drive.

UF2 Bootloader

The bootloader is hosted here; you can compile it yourself by following the instructions in the README. You just need to specify the board to be electronut_labs_papyr. Alternatively, here is a pre-built hex file, and skip ahead to flashing].

The simplest way to enter the bootloader is to double-press the reset button (press twice within 500ms). Once you are in the bootloader, you will see Papyr's LED blinking slowly, and a serial port, and a mass USB storage device (named NRF52BOOT) will appear on your computer. You can drag-and-drop UF2 files into this new mass storage device.

Steps to compile the bootloader are:

$ git clone https://github.com/adafruit/Adafruit_nRF52_Bootloader
$ cd Adafruit_nRF52_Bootloader
$ git submodule update --init --recursive

$ make V=1 SD=s140 SERIAL=/dev/ttyACM1 BOARD=electronut_labs_papyr all combinehex
..
..
ASMFLAGS -x assembler-with-cpp -D__HEAP_SIZE=0 -DCONFIG_GPIO_AS_PINRESET -DBLE_STACK_SUPPORT_REQD -DBSP_DEFINES_ONLY -DSWI_DISABLE0 -DSOFTDEVICE_PRESENT -DFLOAT_ABI_HARD -DNRF52840_XXAA -DS140


   text    data     bss     dec     hex filename
  28452     348   22190   50990    c72e _build-electronut_labs_papyr/electronut_labs_papyr_bootloader-0.2.10-4-gd4c16aa-nosd.out

CR electronut_labs_papyr_bootloader-0.2.10-4-gd4c16aa-nosd.hex
CR electronut_labs_papyr_bootloader-0.2.10-4-gd4c16aa_s140_6.1.1.hex

Upgrading bootloader

In case there is an update for this bootloader, you can upgrade it without a programmer (provided that Papyr does have this bootloader present on it). For that , first make Papyr enter bootloader mode; then you can use the dfu-flash target in the Makefile like:

$ make V=1 SD=s140 SERIAL=/dev/ttyACM1 BOARD=electronut_labs_papyr all combinehex dfu-flash
..
..
CR electronut_labs_papyr_bootloader-0.2.10-4-gd4c16aa-nosd.hex
CR electronut_labs_papyr_bootloader-0.2.10-4-gd4c16aa_s140_6.1.1.hex
Zip created at _build-electronut_labs_papyr/electronut_labs_papyr_bootloader-0.2.10-4-gd4c16aa_s140_6.1.1.zip
adafruit-nrfutil --verbose dfu serial --package _build-electronut_labs_papyr/electronut_labs_papyr_bootloader-0.2.10-4-gd4c16aa_s140_6.1.1.zip -p /dev/ttyACM1 -b 115200 --singlebank --touch 1200
Upgrading target on /dev/ttyACM1 with DFU package /home/tavish/repos/el/extras/circuit_python/Adafruit_nRF52_Bootloader/_build-electronut_labs_papyr/electronut_labs_papyr_bootloader-0.2.10-4-gd4c16aa_s140_6.1.1.zip. Flow control is disabled, Single bank, Touch 1200
Touched serial port /dev/ttyACM1
Opened serial port /dev/ttyACM1
Starting DFU upgrade of type 3, SoftDevice size: 151016, bootloader size: 28792, application size: 0
Sending DFU start packet
Sending DFU init packet
Sending firmware file
########################################
########################################
########################################
########################################
########################################
########################################
########################################
########################################
################################
Activating new firmware

DFU upgrade took 18.96223545074463s
Device programmed.

For above to work, you need to install adafruit-nrfutil:

pip3 install --user adafruit-nrfutil

Note: updating the bootloader only works through the serial bootloader not via UF2. so you can't just drag-and-drop new bootloader hex file into mass storage device.

Flashing the bootloader for the first time

Now that you have the hex file for the bootloader, you can flash it with whatever method you prefer. You can use Segger JLink from an NRF52-DK, or you can use our SWD programmer Bumpy.

If you are using Bumpy (or any other Blackmagicprobe compatible debugger), you can find instructions at:

Converting your firmware to UF2

Some notes on UF2 and flash layout before we flash CircuitPython: Please refer to the bootloader's README for more details.

Once you have the bootloader installed, The application you build is supposed to start from the offset 0x26000 instead of 0x0. Once you have, say, a hex file with the .text section starting at 0x26000; you can use uf2conv.py program in circuitpython repository to convert it to a UF2 file like this:

<path>/<to>/<circuitpython>/tools/uf2/utils/uf2conv.py my_firmware.hex -c -f 0xADA52840

CircuitPython

CircuitPython binary can be flashed using the UF2 bootloader. You can use this pre-built binary and copy it to your NRF52BOOT.

Once CircuitPython firmware is written to your Papyr, it will show up as a serial device and a mass storage device with the name CIRCUITPY.

You can also compile it yourself by following instructions in the CircuitPython repository, just use BOARD=electronut_labs_papyr.

Compilation steps will look like:

$ cd ports/nrf
$ make BOARD=electronut_labs_papyr
Use make V=1, make V=2 or set BUILD_VERBOSE similarly in your environment to increase build verbosity.
QSTR updated


780316 bytes free in flash out of 1048576 bytes ( 1024.0 kb ).
228320 bytes free in ram for stack out of 245760 bytes ( 240.0 kb ).

Create build-electronut_labs_papyr/firmware.uf2
python3 ../../tools/uf2/utils/uf2conv.py -f 0xADA52840 -c -o "build-electronut_labs_papyr/firmware.uf2" build-electronut_labs_papyr/firmware.hex
Converting to uf2, output size: 536576, start address: 0x26000
Wrote 536576 bytes to build-electronut_labs_papyr/firmware.uf2.

Running python code on Papyr

Please see resources on Adafruit's wesbite. You can basically create a file named code.py in the CIRCUITPY drive, and that will get executed every time it is saved. We recommend using the Mu-editor to start with and later you can chose your preferred editor, serial monitor etc.

A sample application to test the e-ink display is here. The sample needs you to have Adafruit CircuitPython BusDevice library on the device. To do that, download latest release, and extract lib/ directory into the CIRCUITPY drive. You also need the PapyrFb library (source code here), and the font file font5x8.bin. Once you have these files, edit CIRCUITPY/code.py to contain the following:

import board
import digitalio
from PapyrFb import *

led = digitalio.DigitalInOut(board.L)
led.direction = digitalio.Direction.OUTPUT

led.value = 0 # on

pfb = PapyrFb()
epd = PapyrEpd(pfb)

pfb.rect(20, 20, pfb.width-40, pfb.height-40, RED)
pfb.rect(22, 22, pfb.width-44, pfb.height-44, BLACK)
pfb.rect(24, 24, pfb.width-48, pfb.height-48, RED)

# larger fonts coming soon
pfb.text("Hello Papyr", 67, 100, BLACK)
pfb.circle(100, 100, 38, RED)

# rings.jpg at end of this page generated from the following snippet
# for i in range(0, 100, 20):
#     pfb.circle(100, 100, i, BLACK)
#     pfb.circle(100, 100, i+4, RED)

epd.refresh()
epd.sleep()

led.value = 1 # off

All the code is available in Papyr's Gitlab repository. If you have the correct files, you directory structure will look like:

.
├── boot_out.txt
├── code.py
├── font5x8.bin
└── lib
    ├── adafruit_bus_device
    │   ├── i2c_device.mpy
    │   ├── __init__.py
    │   └── spi_device.mpy
    └── PapyrFb.mpy

2 directories, 7 files