Commits (220)
Checks: 'clang-diagnostic-*,clang-analyzer-*,bugprone-*'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: none
User: swym
- key: cert-dcl16-c.NewSuffixes
value: 'L;LL;LU;LLU'
- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
value: '1'
- key: google-readability-braces-around-statements.ShortStatementLines
value: '1'
- key: google-readability-function-size.StatementThreshold
value: '800'
- key: google-readability-namespace-comments.ShortNamespaceLines
value: '10'
- key: google-readability-namespace-comments.SpacesBeforeComments
value: '2'
- key: modernize-loop-convert.MaxCopySize
value: '16'
- key: modernize-loop-convert.MinConfidence
value: reasonable
- key: modernize-loop-convert.NamingStyle
value: CamelCase
- key: modernize-pass-by-value.IncludeStyle
value: llvm
- key: modernize-replace-auto-ptr.IncludeStyle
value: llvm
- key: modernize-use-nullptr.NullMacros
value: 'NULL'
......@@ -4,3 +4,5 @@ __pycache__/
......@@ -11,6 +11,21 @@ build:
- merge_requests
- master
stage: build
- ./
- ninja -C build/
- arm-none-eabi-size build/bootloader/bootloader.elf build/epicardium/epicardium.elf build/pycardium/pycardium.elf
- tag
- build/bootloader/bootloader.elf
- build/epicardium/epicardium.elf
- build/pycardium/pycardium.elf
- build/pycardium/pycardium_epicardium.bin
stage: test
image: "derq3k/card10-lint-env:20190806-201106Z-f95b541-dirty"
[submodule "lib/micropython/micropython"]
path = lib/micropython/micropython
url =
[submodule "lib/micropython/micropython-lib"]
path = lib/micropython/micropython-lib
url =
Bluetooth Card10 Service
.. warning::
The specification is still work in progress
The Card10 Service implemented a direct Hardware access of the card10.
BLE Service
The current draft uses following service specification:
- Service
UUID: ``42230200-2342-2342-2342-234223422342``
- Time update characteristic:
UUID: ``42230201-2342-2342-2342-234223422342``
- Vibra characteristic:
UUID: ``4223020f-2342-2342-2342-234223422342``
- Rockets characteristic:
UUID: ``42230210-2342-2342-2342-234223422342``
- Background LED Bottom Left characteristic:
UUID: ``42230211-2342-2342-2342-234223422342``
- Background LED Bottom Right characteristic:
UUID: ``42230212-2342-2342-2342-234223422342``
- Background LED Top Right characteristic:
UUID: ``42230213-2342-2342-2342-234223422342``
- Background LED Top Left characteristic:
UUID: ``42230214-2342-2342-2342-234223422342``
- LEDS dim bottom characteristic:
UUID: ``42230215-2342-2342-2342-234223422342``
- LEDs dim top characteristic:
UUID: ``42230216-2342-2342-2342-234223422342``
- LEDs powersafe characteristic:
UUID: ``42230217-2342-2342-2342-234223422342``
- Flashlight characteristic:
UUID: ``42230218-2342-2342-2342-234223422342``
- LEDs above characteristic:
UUID: ``42230220-2342-2342-2342-234223422342``
- Light sensor characteristic:
UUID: ``422302f0-2342-2342-2342-234223422342``
Time update characteristic
The time update characteristic makes it possible to set the current time given in milliseconds after 1.1.1970 in the UTC timezone. The value is represented as a big endian ``uint64``
- Thu Aug 15 19:40:45 UTC 2019 : ``0x0 0x0 0x1 0x6c 0x96 0xcb 0xf8 0xcc``
Vibra characteristic
The vibra characteristic makes it possible to let the card10 for given millisecound in a ``uint16`` vibrate.
- One secound: ``0xe803``
Rockets characteristic
The Rockets characteristic makes it possible to address every three rockets.
Just write there three byte array, one for evey rocket.
======= ======= =======
0 1 2
------- ------- -------
Rocket0 Rocket1 Rocket2
======= ======= =======
- Enable only Rocket0: ``0xff0000``
- Enable all rockets with 50% brightness: ``0x7f7f7f``
Background LED <Position> characteristic
The Background LEDs <Position> characteristic makes it possible to address the bottom LEDs by position.
Just write there three ``uint8`` for the rgb color.
===== ======= =======
0 1 2
----- ------- -------
red green blue
===== ======= =======
- set led blue: ``0x0000ff``
- disabled: ``0x000000``
LEDs dim <Position> characteristic
The LEDs dim <Position> characteristic makes it possible to dim LEDs by position.
Just write a ``uint8`` between ``1`` and ``8``.
LEDs powersafe characteristic
This characteristic makes it possible to set the LEDs in powersafe mode.
Even when set to zero, the RGB LEDs still individually consume ~1mA.
Powersave intelligently switches the supply power in groups.
This introduces delays in the magnitude of ~10µs, so it can be disabled for high speed applications such as POV
- enabled: ``0x01``
- disabled: ``0x00``
Flashlight characteristic
This characteristic makes it possible to activate the flashlight.
- enabled: ``0x01``
- disabled: ``0x00``
LEDs above characteristic
This characteristic set every 11 leds on the top module at once.
By defining 11x rgb from left to right. You need also to set exchange a bigger MTU to use this feature.
- set a rainbow beginnig with red on the right edge: ``0xff0000ff8b00e8ff005dff0000ff2e00ffb900b9ff002eff5d00ffe800ffff008b``
Light sensor characteristic
The light sensor characteristic makes it possible to read the current value of the light sensor by receiving a ``uint16``.
The range of this sensor is between 0 (``0x0``) and 400 (``0x9001``).
- reading of ``0x0e00`` means **14**
Bluetooth File Transfer
.. warning::
The file transfer specification is still work in progress
File transfer to the card10 is implemented using the custom Low Effort File
Transfer Protocol.
BLE Service
The service consists of two GATT characteristics that act as a bidrectional
link, similar to many BLE UART implementations. The two channels are seen from
the Central perspective and hence named Central TX and Central RX.
The current version uses following service specification:
- Service
UUID: 42230100-2342-2342-2342-234223422342
- Central TX characteristic:
UUID: 42230101-2342-2342-2342-234223422342
- Central RX characteristic:
UUID 42230102-2342-2342-2342-234223422342
read, notify
Low Effort File Transfer Protocol
(Version 1)
This protocol was designed to strike a balance between ease of implementation
and reasonable levels of functionality.
- File push from Central (e.g. Android) to Peripheral (card10)
- Path and file name support
- Chunked data transfer for variable MTUs
- CRC32 error-detection
- Basic error handling
All communication between Central and Peripheral is packet based. The first
byte specifies the packet type using a char followed by an optional CRC and/or
payload, depending on the packet type.
===== ====
0 1-N
----- ----
s path
===== ====
===== ===
0 1-4
----- ---
===== ===
===== ====== =======
0 1-4 4-N
----- ------ -------
c offset payload
===== ====== =======
===== ===
0 1-4
----- ---
===== ===
=== ===
--- ---
=== ===
=== ===
--- ---
=== ===
=== ===
--- ---
=== ===
=== ===
--- ---
=== ===
The file transfer process can be described as a series of states from the view
of the Central role:
.. image:: ../static/ble-low-effort-flow.png
``IDLE`` state:
- Send ``START`` to initiate transfer
``START_SENT`` state:
- Wait for ``START_ACK``
``SEND_READY`` state:
- Send first ``CHUNK``
``CHUNK_SENT`` state:
- Wait for ``CHUNK_ACK``
``SEND_READY`` state:
- Repeat previous two steps until all data is sent
- If the last chunk was sent, send ``FINISH``
``FINISH_SENT`` state:
- Wait for ``FINISH_ACK``
After ``FINISH_ACK`` was received, the transfer is complete and the process can
return to ``IDLE``.
Error Handling
Three types of errors are currently supported:
- CRC errors:
If an ``ACK`` packet contains a CRC that fails the verification, then the
original packet must be retransmitted. If three consecutive attempts to
send a packet fail, then the transfer is aborted.
- ACK timeouts:
If the Central does not receive a required ``ACK`` within 10 seconds, then
the original packet must be retransmitted. If three consecutive attempts to
send a packet fail, then the transfer is aborted.
- Unexpected response:
All steps in the flow described above have exactly one expected response.
If any other packet is received, then the transfer is aborted.
Aborting Transfer
To abort the transfer, the Central role sends an ``ERROR`` packet and returns
to ``IDLE`` after receiving the ``ERROR_ACK``.
If the Peripheral role aborts the transfer, i.e. the Central receives an
``ERROR`` at any point, then it responds with ``ERROR_ACK`` and returns to
.. warning::
As this is a custom file transfer protocol developed under less than ideal
circumstances, it does not provide any guarantees, especially not regarding
reliability or security. The protocol assumes a secure link and a
trustworthy peer, amongst many other things. Use with caution.
......@@ -20,9 +20,9 @@ project = "card10-firmware"
copyright = "2019"
# The full version, including alpha/beta/rc tags
release = subprocess.check_output(
["git", "describe", "--long", "--always"]
release = (
subprocess.check_output(["git", "describe", "--long", "--always"]).decode().strip()
release += "<br />"
release += time.strftime("%F %R")
version = release
......@@ -55,11 +55,14 @@ exclude_patterns = ["output", "Thumbs.db", ".DS_Store", "hawkmoth"]
# - python-sphinx-rtd-theme package (on Debian)
import sphinx_rtd_theme
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
pygments_style = "monokai"
except ImportError:
logger.warning("The Sphinx \"sphinx_rtd_theme\" HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.")
'The Sphinx "sphinx_rtd_theme" HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.'
# Add any paths that contain custom static files (such as style sheets) here,
......@@ -68,9 +71,7 @@ except ImportError:
html_static_path = ["static"]
# Theme Options
html_theme_options = {
"style_external_links": True,
html_theme_options = {"style_external_links": True}
# Show "Edit on GitLab" links
html_show_sourcelink = False
......@@ -86,12 +87,7 @@ html_context = {
# }}}
# -- Options for Auto-Doc ---------------------------------------------------- {{{
autodoc_mock_imports = [
autodoc_mock_imports = ["sys_display", "sys_leds", "ucollections", "urandom", "utime"]
autodoc_member_order = "bysource"
# }}}
......@@ -101,6 +97,7 @@ has_hawkmoth = False
# Attempt importing hawkmoth
import hawkmoth # noqa: F401
cautodoc_root = os.path.abspath("..")
......@@ -108,7 +105,9 @@ try:
has_hawkmoth = True
except ImportError as e:
if == "clang":
logger.warning("hawkmoth requires the clang python module. Documentation for Epicardium API will not be generated.")
"hawkmoth requires the clang python module. Documentation for Epicardium API will not be generated."
# }}}
......@@ -7,6 +7,36 @@ it. The debugger looks like either one in the following pictures:
.. image:: static/debuggers.png
First of all, you need to connect your debugger and card10. There are three
connections that you need (take a look at the above diagram for more info):
* ``HDK``: This connection provides debugging (SWD) and UART.
* ``DEV``: This connection provides power (battery charger) and the native USB
connection (bootloader).
* ``USB-C``: Connect the proved USB-C cable with the side which has the blue
dot, so the blue dots have the same side.
When using the debugger, you will usually have two /dev/ttyACM* devices (one
each for ``HDK`` and ``DEV``). To avoid confusion, allow access without
``sudo`` and tell ModemManager to ignore them, you can use the following udev
rule file (saved under ``/etc/udev/rules.d/99-card10.rules``):
.. code-block:: text
SUBSYSTEM=="tty", ATTRS{idVendor}=="0d28", ATTRS{idProduct}=="0204", MODE="0664", GROUP="plugdev", SYMLINK+="ttyACM-card10-hdk", ENV{ID_MM_DEVICE_IGNORE}="1"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0b6a", ATTRS{idProduct}=="003c", MODE="0664", GROUP="plugdev", SYMLINK+="ttyACM-card10-dev", ENV{ID_MM_DEVICE_IGNORE}="1"
After changing udev rules, you need to tell the udev daemon:
.. code-block:: shell-session
$ sudo udevadm control --reload
Now, additional symlinks (``/dev/ttyACM-card10-hdk`` and
``/dev/ttyACM-card10-dev``) will be created when connecting the card10.
For debugging card10, you need our `own fork`_ of OpenOCD. It contains a patch
......@@ -17,17 +47,17 @@ the following commands:
.. code-block:: shell-session
$ git clone
$ git clone --recursive
$ cd openocd
$ git submodule update --init
$ ./bootstrap
$ ./configure --disable-werror
Make sure ``CMSIS-DAP Compliant Debugger`` is set to **yes (auto)** after
running ``./configure`` (if it is not, you might need to install ``libhidapi-dev``
(Ubuntu)). If you get errors making the documentation you can
``touch doc/`` to skip it and continue with ``make``.
.. warning::
Make sure ``CMSIS-DAP Compliant Debugger`` is set to **yes (auto)** after
running ``./configure`` (if it is not, you might need to install ``libhidapi-dev``
(Ubuntu)). If you get errors making the documentation you can
``touch doc/`` to skip it and continue with ``make``.
.. code-block:: shell-session
......@@ -55,15 +85,6 @@ that package from your distros repositories:
First of all, you need to connect your debugger and card10. There are three
connections that you need (take a look at the above diagram for more info):
* ``HDK``: This connection provides debugging (SWD) and UART.
* ``DEV``: This connection provides power (battery charger) and the native USB
connection (bootloader).
* ``USB-C``: Connect the proved USB-C cable with the side which has the blue
dot, so the blue dots have the same side.
Run OpenOCD from the ``openocd/scripts`` directory in the firmware repository.
Call it as ``openocd -f interface/cmsis-dap.cfg -f target/max32665.cfg``. If
the debugger and card10 are connected correctly, you should see the following
How To Build
If you just want to write MicroPython code for card10, you probably **won't**
need to build the firmware yourself. This page is for people who want to work
on the underlying firmware itself.
need to build the firmware yourself. This page is for people **who want to work
on the underlying firmware itself**.
......@@ -21,27 +21,59 @@ Dependencies
pacman -S arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib
- Fedora
.. code-block:: shell-session
dnf install arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib
- macOS (Note: The card10 firmware team used Linux so far. macOS recommendations here are experimental.)
You can use `Homebrew`_ to install the required tools.
The version of the Arm crosscompiler tool chain is quite important; with the wrong version, e.g. strip and/or ld might throw strange errors.
.. code-block:: shell-session
brew tap px4/px4
brew install px4/px4/gcc-arm-none-eabi-63
brew install coreutils
- Alternative: Download `ARM's GNU toolchain`_. **TODO**
.. _Homebrew:
* **python3**: For meson and various scripts needed for building.
* **meson** (>0.43.0) & **ninja**: Unfortunately most distros only have very old versions
of meson in their repositories. Instead, you'll probably save yourself a lot
of headaches by installing meson from *pip*.
- Ubuntu / Debian:
- Ubuntu / Debian:
.. code-block:: shell-session
apt install ninja-build
pip3 install --user meson
- Arch (has latest *meson* in the repos):
- Arch (has latest *meson* in the repos):
.. code-block:: shell-session
pacman -S meson
- macOS
.. code-block:: shell-session
brew install ninja
pip3 install --user meson # see - you will have to add ~/.local/bin to your PATH.
* **python3-crc16**: Install with ``pip3 install --user crc16``.
* **python3-pillow**: Python Image Library ``pip3 install --user PIL``.
* **python3-pillow**: Python Image Library ``pip3 install --user pillow``.
- Arch
.. code-block:: shell-session
pacman -S python-crc16 python-pillow
.. _ARM's GNU toolchain:
......@@ -68,6 +100,8 @@ firmware features:
- ``-Ddebug_prints=true``: Print more verbose debugging log messages
- ``-Dble_trace=true``: Enable BLE tracing. This will output lots of status
info related to BLE.
- ``-Ddebug_core1=true``: Enable the core 1 SWD lines which are exposed on the
SAO connector. Only use this if you have a debugger which is modified for core 1.
.. warning::
......@@ -21,12 +21,18 @@ Last but not least, if you want to start hacking the lower-level firmware, the
:caption: Pycardium
.. toctree::
:maxdepth: 1
......@@ -47,3 +53,17 @@ Last but not least, if you want to start hacking the lower-level firmware, the
.. toctree::
:maxdepth: 1
:caption: Bluetooth
Indices and tables
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
.. py:module:: buttons
``buttons`` - Push Buttons
The :py:mod:`buttons` module allows you to use card10's push buttons as input
in your scripts.
.. code-block:: python
import buttons
print("Press bottom left or right button:")
while True:
pressed =
buttons.BOTTOM_LEFT | buttons.BOTTOM_RIGHT
if pressed != 0:
if pressed & buttons.BOTTOM_LEFT != 0:
print("Left button pressed!")
if pressed & buttons.BOTTOM_RIGHT != 0:
print("Right button pressed!")
.. py:function:: read(mask)
Read button status.
:param int mask: Mask of buttons to check. Create the mask by ORing
:py:data:`buttons.BOTTOM_LEFT`, :py:data:`buttons.BOTTOM_RIGHT`,
:py:data:`buttons.TOP_RIGHT`, and :py:data:`buttons.TOP_LEFT` (=
:returns: An integer with the bits for pressed buttons set. Use the same
costants as for the mask to check which buttons were pressed.
.. py:data:: BOTTOM_LEFT
Bottom left button.
.. py:data:: BOTTOM_RIGHT
Bottom right button.
.. py:data:: TOP_RIGHT
Top right button.
.. py:data:: TOP_LEFT
Top left button (Reset button).
.. py:data:: RESET
Top left button (Reset button).
......@@ -9,160 +9,172 @@ Color Class
The color module also contains a few constanst for commonly used colors:
.. py:data:: color.BLACK
.. py:data:: color.WHITE
.. py:data:: color.RED
.. py:data:: color.GREEN
.. py:data:: color.YELLOW
.. py:data:: color.BLUE
.. py:data:: color.MAGENTA
.. py:data:: color.CYAN
Camp Colors
.. py:data:: CHAOSBLUE
.. py:data:: CHAOSBLUE_DARK
.. py:data:: COMMYELLOW
.. py:data:: COMMYELLOW_DARK
.. py:data:: CAMPGREEN
.. py:data:: CAMPGREEN_DARK
.. py:data:: BLACK
.. py:data:: WHITE
.. py:data:: RED
.. py:data:: GREEN
.. py:data:: YELLOW
.. py:data:: BLUE
.. py:data:: MAGENTA
.. py:data:: CYAN
.. py:module:: htmlcolor
``htmlcolor`` - Color Constants
The ``htmlcolor`` module contains even more color constants. Note
that loading the ``htmlcolor`` module will require ~12K of RAM.
.. py:data:: htmlcolor.ALICEBLUE
.. py:data:: htmlcolor.ANTIQUEWHITE
.. py:data:: htmlcolor.AQUA
.. py:data:: htmlcolor.AQUAMARINE
.. py:data:: htmlcolor.AZURE
.. py:data:: htmlcolor.BEIGE
.. py:data:: htmlcolor.BISQUE
.. py:data:: htmlcolor.BLACK
.. py:data:: htmlcolor.BLANCHEDALMOND
.. py:data:: htmlcolor.BLUE
.. py:data:: htmlcolor.BLUEVIOLET
.. py:data:: htmlcolor.BROWN
.. py:data:: htmlcolor.BURLYWOOD
.. py:data:: htmlcolor.CADETBLUE
.. py:data:: htmlcolor.CHARTREUSE
.. py:data:: htmlcolor.CHOCOLATE
.. py:data:: htmlcolor.CORAL
.. py:data:: htmlcolor.CORNFLOWERBLUE
.. py:data:: htmlcolor.CORNSILK
.. py:data:: htmlcolor.CRIMSON
.. py:data:: htmlcolor.CYAN
.. py:data:: htmlcolor.DARKBLUE
.. py:data:: htmlcolor.DARKCYAN
.. py:data:: htmlcolor.DARKGOLDENROD
.. py:data:: htmlcolor.DARKGRAY
.. py:data:: htmlcolor.DARKGREEN
.. py:data:: htmlcolor.DARKKHAKI
.. py:data:: htmlcolor.DARKMAGENTA
.. py:data:: htmlcolor.DARKOLIVEGREEN
.. py:data:: htmlcolor.DARKORANGE
.. py:data:: htmlcolor.DARKORCHID
.. py:data:: htmlcolor.DARKRED
.. py:data:: htmlcolor.DARKSALMON
.. py:data:: htmlcolor.DARKSEAGREEN
.. py:data:: htmlcolor.DARKSLATEBLUE
.. py:data:: htmlcolor.DARKSLATEGRAY
.. py:data:: htmlcolor.DARKTURQUOISE
.. py:data:: htmlcolor.DARKVIOLET
.. py:data:: htmlcolor.DEEPPINK
.. py:data:: htmlcolor.DEEPSKYBLUE
.. py:data:: htmlcolor.DIMGRAY
.. py:data:: htmlcolor.DODGERBLUE
.. py:data:: htmlcolor.FIREBRICK
.. py:data:: htmlcolor.FLORALWHITE
.. py:data:: htmlcolor.FORESTGREEN
.. py:data:: htmlcolor.FUCHSIA
.. py:data:: htmlcolor.GAINSBORO
.. py:data:: htmlcolor.GHOSTWHITE
.. py:data:: htmlcolor.GOLD
.. py:data:: htmlcolor.GOLDENROD
.. py:data:: htmlcolor.GRAY
.. py:data:: htmlcolor.GREEN
.. py:data:: htmlcolor.GREENYELLOW
.. py:data:: htmlcolor.HONEYDEW
.. py:data:: htmlcolor.HOTPINK
.. py:data:: htmlcolor.INDIANRED
.. py:data:: htmlcolor.INDIGO
.. py:data:: htmlcolor.IVORY
.. py:data:: htmlcolor.KHAKI
.. py:data:: htmlcolor.LAVENDER
.. py:data:: htmlcolor.LAVENDERBLUSH
.. py:data:: htmlcolor.LAWNGREEN
.. py:data:: htmlcolor.LEMONCHIFFON
.. py:data:: htmlcolor.LIGHTBLUE
.. py:data:: htmlcolor.LIGHTCORAL
.. py:data:: htmlcolor.LIGHTCYAN
.. py:data:: htmlcolor.LIGHTGOLDENRODYELLOW
.. py:data:: htmlcolor.LIGHTGRAY
.. py:data:: htmlcolor.LIGHTGREEN
.. py:data:: htmlcolor.LIGHTPINK
.. py:data:: htmlcolor.LIGHTSALMON
.. py:data:: htmlcolor.LIGHTSEAGREEN
.. py:data:: htmlcolor.LIGHTSKYBLUE
.. py:data:: htmlcolor.LIGHTSLATEGRAY
.. py:data:: htmlcolor.LIGHTSTEELBLUE
.. py:data:: htmlcolor.LIGHTYELLOW
.. py:data:: htmlcolor.LIME
.. py:data:: htmlcolor.LIMEGREEN
.. py:data:: htmlcolor.LINEN
.. py:data:: htmlcolor.MAGENTA
.. py:data:: htmlcolor.MAROON
.. py:data:: htmlcolor.MEDIUMAQUAMARINE
.. py:data:: htmlcolor.MEDIUMBLUE
.. py:data:: htmlcolor.MEDIUMORCHID
.. py:data:: htmlcolor.MEDIUMPURPLE
.. py:data:: htmlcolor.MEDIUMSEAGREEN
.. py:data:: htmlcolor.MEDIUMSLATEBLUE
.. py:data:: htmlcolor.MEDIUMSPRINGGREEN
.. py:data:: htmlcolor.MEDIUMTURQUOISE
.. py:data:: htmlcolor.MEDIUMVIOLETRED
.. py:data:: htmlcolor.MIDNIGHTBLUE
.. py:data:: htmlcolor.MINTCREAM
.. py:data:: htmlcolor.MISTYROSE
.. py:data:: htmlcolor.MOCCASIN
.. py:data:: htmlcolor.NAVAJOWHITE
.. py:data:: htmlcolor.NAVY
.. py:data:: htmlcolor.OLDLACE
.. py:data:: htmlcolor.OLIVE
.. py:data:: htmlcolor.OLIVEDRAB
.. py:data:: htmlcolor.ORANGE
.. py:data:: htmlcolor.ORANGERED
.. py:data:: htmlcolor.ORCHID
.. py:data:: htmlcolor.PALEGOLDENROD
.. py:data:: htmlcolor.PALEGREEN
.. py:data:: htmlcolor.PALETURQUOISE
.. py:data:: htmlcolor.PALEVIOLETRED
.. py:data:: htmlcolor.PAPAYAWHIP
.. py:data:: htmlcolor.PEACHPUFF
.. py:data:: htmlcolor.PERU
.. py:data:: htmlcolor.PINK
.. py:data:: htmlcolor.PLUM
.. py:data:: htmlcolor.POWDERBLUE
.. py:data:: htmlcolor.PURPLE
.. py:data:: htmlcolor.RED
.. py:data:: htmlcolor.ROSYBROWN
.. py:data:: htmlcolor.ROYALBLUE
.. py:data:: htmlcolor.SADDLEBROWN
.. py:data:: htmlcolor.SALMON
.. py:data:: htmlcolor.SANDYBROWN
.. py:data:: htmlcolor.SEAGREEN
.. py:data:: htmlcolor.SEASHELL
.. py:data:: htmlcolor.SIENNA
.. py:data:: htmlcolor.SILVER
.. py:data:: htmlcolor.SKYBLUE
.. py:data:: htmlcolor.SLATEBLUE
.. py:data:: htmlcolor.SLATEGRAY
.. py:data:: htmlcolor.SNOW
.. py:data:: htmlcolor.SPRINGGREEN
.. py:data:: htmlcolor.STEELBLUE
.. py:data:: htmlcolor.TAN
.. py:data:: htmlcolor.TEAL
.. py:data:: htmlcolor.THISTLE
.. py:data:: htmlcolor.TOMATO
.. py:data:: htmlcolor.TURQUOISE
.. py:data:: htmlcolor.VIOLET
.. py:data:: htmlcolor.WHEAT
.. py:data:: htmlcolor.WHITE
.. py:data:: htmlcolor.WHITESMOKE
.. py:data:: htmlcolor.YELLOW
.. py:data:: htmlcolor.YELLOWGREEN
.. py:data:: ALICEBLUE
.. py:data:: ANTIQUEWHITE
.. py:data:: AQUA
.. py:data:: AQUAMARINE
.. py:data:: AZURE
.. py:data:: BEIGE
.. py:data:: BISQUE
.. py:data:: BLACK
.. py:data:: BLUE
.. py:data:: BLUEVIOLET
.. py:data:: BROWN
.. py:data:: BURLYWOOD
.. py:data:: CADETBLUE
.. py:data:: CHARTREUSE
.. py:data:: CHOCOLATE
.. py:data:: CORAL
.. py:data:: CORNSILK
.. py:data:: CRIMSON
.. py:data:: CYAN
.. py:data:: DARKBLUE
.. py:data:: DARKCYAN
.. py:data:: DARKGOLDENROD
.. py:data:: DARKGRAY
.. py:data:: DARKGREEN
.. py:data:: DARKKHAKI
.. py:data:: DARKMAGENTA
.. py:data:: DARKORANGE
.. py:data:: DARKORCHID
.. py:data:: DARKRED
.. py:data:: DARKSALMON
.. py:data:: DARKSEAGREEN
.. py:data:: DARKSLATEBLUE
.. py:data:: DARKSLATEGRAY
.. py:data:: DARKTURQUOISE
.. py:data:: DARKVIOLET
.. py:data:: DEEPPINK
.. py:data:: DEEPSKYBLUE
.. py:data:: DIMGRAY
.. py:data:: DODGERBLUE
.. py:data:: FIREBRICK
.. py:data:: FLORALWHITE
.. py:data:: FORESTGREEN
.. py:data:: FUCHSIA
.. py:data:: GAINSBORO
.. py:data:: GHOSTWHITE
.. py:data:: GOLD
.. py:data:: GOLDENROD
.. py:data:: GRAY
.. py:data:: GREEN
.. py:data:: GREENYELLOW
.. py:data:: HONEYDEW
.. py:data:: HOTPINK
.. py:data:: INDIANRED
.. py:data:: INDIGO
.. py:data:: IVORY
.. py:data:: KHAKI
.. py:data:: LAVENDER
.. py:data:: LAVENDERBLUSH
.. py:data:: LAWNGREEN
.. py:data:: LEMONCHIFFON
.. py:data:: LIGHTBLUE
.. py:data:: LIGHTCORAL
.. py:data:: LIGHTCYAN
.. py:data:: LIGHTGRAY
.. py:data:: LIGHTGREEN
.. py:data:: LIGHTPINK
.. py:data:: LIGHTSALMON
.. py:data:: LIGHTSEAGREEN
.. py:data:: LIGHTSKYBLUE
.. py:data:: LIGHTYELLOW
.. py:data:: LIME
.. py:data:: LIMEGREEN
.. py:data:: LINEN
.. py:data:: MAGENTA
.. py:data:: MAROON
.. py:data:: MEDIUMBLUE
.. py:data:: MEDIUMORCHID
.. py:data:: MEDIUMPURPLE
.. py:data:: MIDNIGHTBLUE
.. py:data:: MINTCREAM
.. py:data:: MISTYROSE
.. py:data:: MOCCASIN
.. py:data:: NAVAJOWHITE
.. py:data:: NAVY
.. py:data:: OLDLACE
.. py:data:: OLIVE
.. py:data:: OLIVEDRAB
.. py:data:: ORANGE
.. py:data:: ORANGERED
.. py:data:: ORCHID
.. py:data:: PALEGOLDENROD
.. py:data:: PALEGREEN
.. py:data:: PALETURQUOISE
.. py:data:: PALEVIOLETRED
.. py:data:: PAPAYAWHIP
.. py:data:: PEACHPUFF
.. py:data:: PERU
.. py:data:: PINK
.. py:data:: PLUM
.. py:data:: POWDERBLUE
.. py:data:: PURPLE
.. py:data:: RED
.. py:data:: ROSYBROWN
.. py:data:: ROYALBLUE
.. py:data:: SADDLEBROWN
.. py:data:: SALMON
.. py:data:: SANDYBROWN
.. py:data:: SEAGREEN
.. py:data:: SEASHELL
.. py:data:: SIENNA
.. py:data:: SILVER
.. py:data:: SKYBLUE
.. py:data:: SLATEBLUE
.. py:data:: SLATEGRAY
.. py:data:: SNOW
.. py:data:: SPRINGGREEN
.. py:data:: STEELBLUE
.. py:data:: TAN
.. py:data:: TEAL
.. py:data:: THISTLE
.. py:data:: TOMATO
.. py:data:: TURQUOISE
.. py:data:: VIOLET
.. py:data:: WHEAT
.. py:data:: WHITE
.. py:data:: WHITESMOKE
.. py:data:: YELLOW
.. py:data:: YELLOWGREEN
.. py:module:: gpio
``gpio`` - GPIO Pins
The :py:mod:`gpio` module allows you to use card10's GPIO pins as input and
output in your scripts.
.. code-block:: python
import gpio
gpio.set_mode(gpio.WRISTBAND_1, gpio.mode.OUTPUT)
gpio.write(gpio.WRISTBAND_1, True)
gpio.set_mode(gpio.WRISTBAND_2, gpio.mode.INPUT | gpio.mode.PULL_UP)
state =
print("State of Wristband pin 2:", state)
.. py:function:: set_mode(pin, mode)
Configure GPIO pin state.
:param int pin: ID of the pin to be configured.
:param int mode: An integer with the bits for the wanted mode set. Create your
integer by ORing :py:data:`gpio.mode.OUTPUT`, :py:data:`gpio.mode.INPUT`,
:py:data:`gpio.mode.PULL_UP`, :py:data:`gpio.mode.PULL_DOWN`.
.. py:function:: get_mode(pin)
Get GPIO pin state.
:param int pin: ID of the pin of to get the mode of.
:returns: An integer with the configure mode bits set.
.. py:function:: write(pin, value)
Write a value to a GPIO pin.
:param int pin: ID of the pin of to get the mode of.
:param bool value: New pin value.
.. py:function:: read(pin)
Read GPIO pin value.
:param int pin: ID of the pin of to get the mode of.
:returns: Current value of the GPIO pin.
.. py:data:: WRISTBAND_1
Pin ID for Wristband GPIO 1.
.. py:data:: WRISTBAND_2
Pin ID for Wristband GPIO 2.
.. py:data:: WRISTBAND_3
Pin ID for Wristband GPIO 3.
.. py:data:: WRISTBAND_4
Pin ID for Wristband GPIO 4.
.. py:module:: gpio.mode
.. py:data:: OUTPUT
Configures a pin as output.
.. py:data:: INPUT
Configures a pin as input.
.. py:data:: PULL_UP
Enables the internal pull-up resistor of a pin.
.. py:data:: PULL_DOWN
Enables the internal pull-down resistor of a pin.
``leds`` - LEDs
The ``leds`` module provides functions to interact with card10's RGB LEDs.
This is the 11 LEDs above the display and 4 LEDs on the underside of the
top-board, in the four corners.
.. py:function:: leds.set(led, color)
.. automodule:: leds
Set one of the card10's RGB LEDs to a certain color.
``ledfx`` - LED Effects
.. code-block:: python
import leds, color
# Set all of the top LEDs to red
for i in range(11):
leds.set(i, color.RED)
:param led: Which led to set. 0-10 are the leds on the top
and 11-14 are the 4 "ambient" leds.
:param color: What color to set the led to. Should be a
:py:class:`color.Color` but any list/tuple with 3 elements
will work just as well.
.. py:data:: leds.BOTTOM_RIGHT
Index of the LED in the bottom right of card10.
.. py:data:: leds.BOTTOM_LEFT
Index of the LED in the bottom left of card10.
.. py:data:: leds.TOP_RIGHT
Index of the LED in the top right of card10.
.. py:data:: leds.TOP_LEFT
Index of the LED in the top left of card10.
.. automodule:: ledfx
.. py:module:: light_sensor
``light_sensor`` - Ambient Brightness
On the harmonic board, there is an IR-LED which can be used in reverse as a
crude brightness sensor. Values returned are in no particular unit but seem to
be fairly stable.
.. py:function:: light_sensor.start()
.. py:function:: start()
Turn on the ADC and start reading brightness values. This function must be
called before any measurements can be taken.
Turn on the ADC and start reading brightness values. (In past this function must be
called before any measurements can be taken.)
.. py:function:: light_sensor.get_reading()
.. py:function:: get_reading()
Get an ambient brightness reading. The returned value is in no particular
unit, though it seems to be fairly stable. Common values:
unit, though it seems to be fairly stable. The value could be between 0 and 400. Common values:
- ~8: Very dark are
- ~17: Typical hackerspace brightness
......@@ -20,6 +22,6 @@ be fairly stable.
:returns: A brightness reading in no particular unit
.. py:function:: light_sensor.stop()
.. py:function:: stop()
Stop the ADC.
.. py:module:: os
``os`` - OS Functions
The ``os`` module allows access to a few core functionalities of Epicardium and
functions found in CPythons ``os`` module.
.. py:function:: unlink(path)
Unlink (remove) a file.
:param str path: The file to remove.
.. py:function:: listdir(dir)
List contents of a directory.
:param str dir: Path to the directory to list.
:returns: A list of entities (files or subdirectories) in the directory
.. py:function:: urandom(n)
Return ``n`` random bytes.
:param int n: Number of random bytes to retrieve.
:returns: ``bytes()`` object with ``n`` random bytes.
.. py:function:: exit(ret = None)
Exit from the current app and return to the menu.
:param int ret: Optional return code, same semantics as Posix (``0`` means
:return: This function will never return.
.. py:function:: exec(name)
Try executing a new app, stopping the currently running one.
``name`` is the path to either a l0dable (ending in ``.elf``) or a python
script (ending in ``.py``). If the path does not lead to an executable file,
``os.exec()`` will raise an exception.
:param str name: Path to new app/script/l0dable.
:return: This function never returns. It can, however raise an exception.
.. py:function:: read_battery()
Read the current battery voltage in V. Please keep in mind that battery
voltage behaves exponentially when interpreting this value.
.. warning::
Card10 will hard-shutdown once the voltage drops below 3.4 V
.. py:function:: reset()
Reboot card10.
.. warning::
Please only call this function if absolutely necessary. In most cases
you'll want to just :py:func:`os.exit` instead.
.. py:module:: personal_state
``personal_state`` - Personal State
The :py:mod:`personal_state` module allows you to set and get the card10 users
`personal state`_ from your script. The personal state is displayed on the
top-left LED on the bottom of the harmonics board. While the personal state is
set the LED can't be controlled by the :py:mod:`leds` module.
.. _personal state:
.. code-block:: python
import personal_state
# Enable the "camp" state only while the app is running.
personal_state.set(personal_state.CAMP, False)
# Enable the "chaos" state and keep it after the app exits.
personal_state.set(personal_state.CHAOS, True)
# Query the currently configured state and if it's persistent.
state, persistent = personal_state.get()
# Clear the currently configured state
.. py:function:: set(state, persistent)
Set the users personal state.
:param int state: ID of the personal state to set. Must be one of
:py:data:`personal_state.NO_CONTACT`, :py:data:`personal_state.CHAOS`,
:py:data:`personal_state.COMMUNICATION`, :py:data:`personal_state.CAMP`.
:param int persistent: Controls whether the personal state is persistent. A
persistent state is not reset when the pycardium application is changed
or restarted. In persistent mode the personal state LED is not
controllable by the pycardium application.
.. py:function:: clear()
Clears a previously set personal state.
If no personal state was set this function does nothing. It does not matter
if a set state is marked as persistent or not.
.. py:function:: get()
Get the users personal state.
:returns: A tuple containing the currently set state and a boolean
indicating if it's persistent or not.
.. py:data:: NO_STATE
State ID reported when no personal state is set.
.. py:data:: NO_CONTACT
State ID for the "No Contact" personal state.
.. py:data:: CHAOS
State ID for the "Chaos" personal state.
.. py:data:: COMMUNICATION
State ID for the "Communicatoin" personal state.
.. py:data:: CAMP
State ID for the "Camp" personal state.
``pride`` - Pride flags
The ``pride`` module provides an easy interface to print pride flags to the top LEDs and the display.
.. automodule:: pride
MicroPython Standard Library
Pycardium contains some modules from the MicroPython standard library. These
.. py:module:: ubinascii
Refer to the official `MicroPython docs for ubinascii`_.
.. _MicroPython docs for ubinascii:
.. py:module:: ucollections
.. py:function:: namedtuple(...)
See the official `MicroPython docs for namedtuple`_ for details.
.. _MicroPython docs for namedtuple:
.. py:module:: uerrno
Refer to the offical `MicroPython docs for uerrno`_.
.. _MicroPython docs for uerrno:
.. py:module:: uheapq
Refer to the offical `MicroPython docs for uheapq`_.
.. _MicroPython docs for uheapq:
.. py:module:: uio
Refer to the offical `MicroPython docs for uio`_.
.. _MicroPython docs for uio:
.. py:module:: ujson
Refer to the offical `MicroPython docs for ujson`_.
.. _MicroPython docs for ujson:
.. py:module:: urandom
Pseudo-random number generator.
.. py:function:: choice(seq)
Return a random element from the non-empty sequence ``seq``.
.. py:function:: getrandbits(k)
Returns a Python integer with ``k`` random bits.
.. py:function:: randint(a, b)
Return a random integer ``N`` such that ``a <= N <= b``. Alias for
:py:func:`randrange(a, b+1) <urandom.randrange>`.
.. py:function:: random()
Return the next random floating point number in the range [0.0, 1.0).
.. py:function:: randrange(start, stop, [step])
.. py:function:: randrange(stop)
Return a randomly selected element from ``range(start, stop, step)``. This
is equivalent to ``urandom.choice(range(start, stop, step))``, but doesn’t
actually build a range object.
The positional argument pattern matches that of ``range()``. Keyword
arguments should not be used because the function may use them in unexpected
.. py:function:: seed(n)
Seed the pseudo-random number generator from ``n``.
.. note::
CPython does not provide a :py:func:`seed` function. This is a
difference in the MicroPython implementation.
.. py:function:: uniform(a, b)
Return a random floating point number ``N`` such that ``a <= N <= b`` for
``a <= b`` and ``b <= N <= a`` for ``b < a``.
The end-point value ``b`` may or may not be included in the range depending
on floating-point rounding in the equation ``a + (b-a) * random()``.
.. py:module:: ure
Minimal regular expression library. Refer to the offical `MicroPython docs for ure`_.
.. _MicroPython docs for ure:
.. py:module:: ustruct
Refer to the offical `MicroPython docs for ustruct`_.
.. _MicroPython docs for ustruct:
``utime`` contains non-standard functions as well. Please refer to our
dedicated :py:mod:`utime` docs.
Python Standard Library
Additionally to the MicroPython module, Pycardium contains a subset of the
CPython standard library, as implemented by `micropython-lib`_. The following
modules are included:
.. _micropython-lib:
.. py:module:: collections
Collections module.
.. py:module:: contextlib
Contextlib module.
.. py:module:: functools
Functools module.
.. py:module:: itertools
Itertools module.
.. warning::
:py:func:`itertools.tee` is not implemented correctly.
.. py:module:: string
String module.
.. py:module:: struct
Struct module.
.. py:module:: uuid
.. py:class:: UUID(hex=None, bytes=None, int=None, version=None)
Create a new UUID object.
Exactly one of ``hex``, ``bytes``, or ``int`` must be given. The
``version`` argument is optional; if given, the resulting UUID will have its
variant and version set according to RFC 4122, overriding the given ``hex``,
``bytes``, or ``int``.
.. code-block:: python
UUID(bytes='\x12\x34\x56\x78' * 4)
.. py:attribute:: bytes
UUID as ``bytes()`` object
.. py:attribute:: node
Node of this UUID
.. py:attribute:: hex
Hex-String representation of this UUID