Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • card10/firmware
  • annejan/firmware
  • astro/firmware
  • fpletz/firmware
  • gerd/firmware
  • fleur/firmware
  • swym/firmware
  • l/firmware
  • uberardy/firmware
  • wink/firmware
  • madonius/firmware
  • mot/firmware
  • filid/firmware
  • q3k/firmware
  • hauke/firmware
  • Woazboat/firmware
  • pink/firmware
  • mossmann/firmware
  • omniskop/firmware
  • zenox/firmware
  • trilader/firmware
  • Danukeru/firmware
  • shoragan/firmware
  • zlatko/firmware
  • sistason/firmware
  • datenwolf/firmware
  • bene/firmware
  • amedee/firmware
  • martinling/firmware
  • griffon/firmware
  • chris007/firmware
  • adisbladis/firmware
  • dbrgn/firmware
  • jelly/firmware
  • rnestler/firmware
  • mh/firmware
  • ln/firmware
  • penguineer/firmware
  • monkeydom/firmware
  • jens/firmware
  • jnaulty/firmware
  • jeffmakes/firmware
  • marekventur/firmware
  • pete/firmware
  • h2obrain/firmware
  • DooMMasteR/firmware
  • jackie/firmware
  • prof_r/firmware
  • Draradech/firmware
  • Kartoffel/firmware
  • hinerk/firmware
  • abbradar/firmware
  • JustTB/firmware
  • LuKaRo/firmware
  • iggy/firmware
  • ente/firmware
  • flgr/firmware
  • Lorphos/firmware
  • matejo/firmware
  • ceddral7/firmware
  • danb/firmware
  • joshi/firmware
  • melle/firmware
  • fitch/firmware
  • deurknop/firmware
  • sargon/firmware
  • markus/firmware
  • kloenk/firmware
  • lucaswerkmeister/firmware
  • derf/firmware
  • meh/firmware
  • dx/card10-firmware
  • torben/firmware
  • yuvadm/firmware
  • AndyBS/firmware
  • klausdieter1/firmware
  • katzenparadoxon/firmware
  • xiretza/firmware
  • ole/firmware
  • techy/firmware
  • thor77/firmware
  • TilCreator/firmware
  • fuchsi/firmware
  • dos/firmware
  • yrlf/firmware
  • PetePriority/firmware
  • SuperVirus/firmware
  • sur5r/firmware
  • tazz/firmware
  • Alienmaster/firmware
  • flo_h/firmware
  • baldo/firmware
  • mmu_man/firmware
  • Foaly/firmware
  • sodoku/firmware
  • Guinness/firmware
  • ssp/firmware
  • led02/firmware
  • Stormwind/firmware
  • arist/firmware
  • coon/firmware
  • mdik/firmware
  • pippin/firmware
  • royrobotiks/firmware
  • zigot83/firmware
  • mo_k/firmware
106 results
Show changes
Showing
with 904 additions and 73 deletions
.. 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.
CPython-Like
------------
.. 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
``dir``.
.. py:function:: mkdir(path)
Create a directory named *path*.
:param str path: Path to the directory to create. Only the last component
of this path will be created.
.. py:function:: rename(src, dst)
Rename the file or directory *src* to *dst*. If *dst* exists, the operation
will fail.
:param str src: Path to source file to rename.
:param str dst: Destination path to rename to. Must not exist before
calling :py:func:`os.rename`.
.. py:function:: unlink(path)
Unlink (remove) a file.
:param str path: The file to remove.
.. py:function:: urandom(n)
Return ``n`` random bytes.
.. versionadded:: 1.3
:param int n: Number of random bytes to retrieve.
:returns: ``bytes()`` object with ``n`` random bytes.
Card10-Specific
---------------
.. 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
success).
: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:function:: usbconfig(config_type)
Change active USB configuration. By default, card10 boots with
:py:data:`os.USB_SERIAL` active.
This will deactivate the currently active USB configuration. This means
that, if you activate :py:data:`os.USB_FLASH` while :py:data:`os.USB_SERIAL`
was active, the USB serial will be disconnected.
:param config_type: Selects which config to activate. Possible
values are :py:data:`os.USB_SERIAL`, :py:data:`os.USB_FLASH`,
or :py:data:`os.USB_NONE`.
.. versionadded:: 1.11
.. py:data:: USB_NONE
No USB device active.
.. py:data:: USB_SERIAL
CDC-ACM serial device active.
.. py:data:: USB_FLASH
Mass-Storage device active.
.. py:function:: fs_is_attached()
Check whether the filesystem is currently attached to card10 (or whether a connected
USB host is currently holding control over it and possibly writing to it).
:returns:
- ``True`` if the filesystem is attached to card10 and an app can read and
write files.
- ``False`` if the filesystem is not available to card10 because a USB
host is currently controlling it.
.. versionadded: 1.18
......@@ -33,11 +33,56 @@ systems this device will be called ``/dev/ttyACM0`` or ``/dev/ttyACM1``.
Choose a terminal-emulator of your liking and open the above mentioned device.
Baud-rate is 115200. Some options are:
* **screen**: ``screen /dev/ttyACM0 115200``
* **picocom**: ``picocom -b 115200 /dev/ttyACM0``
* **screen**: ``sudo screen /dev/ttyACM0 115200``
* **picocom**: ``sudo picocom -b 115200 /dev/ttyACM0``
After connecting, reboot card10 and you should see the MicroPython REPL pop up.
After connecting, reboot reset the card10 via the power button (left upper
corner) and you should see the output of **menu.py** script (it's located in
*preload/menu.py*). You can press CTRL-C to interrupt the script and jump into
the MicroPython prompt.
.. todo::
To switch on the blue fairy dust you must import the led python module::
Getting Started Guide for people interested in writing Python code.
import leds
and power it on::
leds.set_rocket(0, 31)
.. note::
If you're using iOS/Mac then you can connect to your serial console using:
.. code-block:: shell-session
screen /dev/tty.usbmodem* 115200
You can now see in your console what buttons you have pressed and your
console outputs/logs. With ``CTRL+C`` you exit the console.
REPL modes
^^^^^^^^^^
MicroPython supports a different REPL modes over the serial console. The modes
can be changed on every new line.
Normal mode
"""""""""""
This is the mode you will first see. You can switch to it by pressing CTRL-B.
If you are in a other mode you can return to this mode by pressing CTRL-B too.
Paste mode
""""""""""
You can enter the paste mode by pressing CTRL-E and you can simple copy 'n'
paste your source code into the console and it will be interpreted and executed
line by line. Every new line will be reply by the prompt with **===**.
RAW mode
""""""""
The RAW mode to be intendend for the usage with tools. By pressing CTRL-A you
will enter the RAW REPL mode. The type in code will not printed. By pressing
CTRL-D the whole entered code will be evaluated and executed. The board will
reply with **OK** and print after that the output (print commands) of the code
or give you tracebacks if an error occured.
You can use **pycard10** (tools/pycard10.py) to execute python files from your
PC directly on the card10.
.. 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: https://card10.badge.events.ccc.de/ps/
**Example**:
.. 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
personal_state.clear()
.. 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.
``png`` - PNG Decoder
=====================
The ``png`` module provides functions to decode PNG files into raw pixel data
which can be displayed using the card10's display or its LEDs.
.. automodule:: png
:members:
.. py:module:: power
``power`` - PMIC power module handling
======================================
.. versionadded:: 1.4
The :py:mod:`power` module allows you to read the card10's power status
in your scripts.
**Example**:
.. code-block:: python
import power
print(power.read_battery_voltage())
.. py:function:: read_battery_voltage()
Read the 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
.. versionadded:: 1.4
.. py:function:: read_battery_current()
Read the battery-side current flow in A.
.. versionadded:: 1.4
.. py:function:: read_chargein_voltage()
Read the charge voltage in V.
.. versionadded:: 1.4
.. py:function:: read_chargein_current()
Read the charge current in A.
.. versionadded:: 1.4
.. py:function:: read_system_voltage()
Read the system-side voltate in V.
.. versionadded:: 1.4
.. py:function:: read_thermistor_voltage()
Read the thermistor voltage in V.
There is a resistor network from GND over a thermistor
(10K at room temperature) over 10K to the Thermistor Bias voltage.
This reads the voltage between thermistor and resistor.
.. versionadded:: 1.4
``pride`` - Pride flags
=======================
The ``pride`` module provides an easy interface to print pride flags to the top LEDs and the display.
.. automodule:: pride
:members:
``simple_menu`` - Draw a Menu
=============================
.. versionadded:: 1.4
To allow quickly hacking some scripts, Pycardium has a small library for
displaying menus. You can use it like this:
.. code-block:: python
import color
import simple_menu
class MyMenu(simple_menu.Menu):
color_1 = color.CAMPGREEN
color_2 = color.CAMPGREEN_DARK
def on_select(self, name, index):
print("{!r} was selected!".format(name))
if __name__ == "__main__":
MyMenu(["foo", "bar", "baz"]).run()
.. autoclass:: simple_menu.Menu
:members:
.. autodata:: simple_menu.TIMEOUT
.. autofunction:: simple_menu.button_events
MicroPython Standard Library
============================
Pycardium contains some modules from the MicroPython standard library.
Some modules below use a standard Python name, but prefixed with “u”,
e.g. ujson instead of json. This is to signify that such a module is a
micro-library, i.e. implements only a subset of CPython module
functionality. Please refer to the official `MicroPython docs`_ for an
explanation why.
All u-name modules can also be imported using their non-u-name. E.g.
``import utime`` and import ``import time`` will both work.
.. _MicroPython docs: http://docs.micropython.org/en/latest/library/index.html#python-standard-libraries-and-micro-libraries
.. py:module:: framebuf
``framebuf``
------------
Refer to the official `MicroPython docs for framebuf`_.
.. _MicroPython docs for framebuf: https://docs.micropython.org/en/latest/library/framebuf.html
.. py:module:: ubinascii
``ubinascii``
-------------
Refer to the official `MicroPython docs for ubinascii`_.
.. _MicroPython docs for ubinascii: http://docs.micropython.org/en/latest/library/ubinascii.html
.. py:module:: ucollections
``ucollections``
----------------
.. py:function:: namedtuple(...)
See the official `MicroPython docs for namedtuple`_ for details.
.. _MicroPython docs for namedtuple: http://docs.micropython.org/en/latest/library/ucollections.html#ucollections.namedtuple
.. py:module:: uerrno
``uerrno``
----------
Refer to the offical `MicroPython docs for uerrno`_.
.. _MicroPython docs for uerrno: http://docs.micropython.org/en/latest/library/uerrno.html
.. py:module:: uheapq
``uheapq``
----------
Refer to the offical `MicroPython docs for uheapq`_.
.. _MicroPython docs for uheapq: http://docs.micropython.org/en/latest/library/uheapq.html
.. py:module:: uio
``uio``
-------
Refer to the offical `MicroPython docs for uio`_.
.. _MicroPython docs for uio: http://docs.micropython.org/en/latest/library/uio.html
.. py:module:: ujson
``ujson``
---------
Refer to the offical `MicroPython docs for ujson`_.
.. _MicroPython docs for ujson: http://docs.micropython.org/en/latest/library/ujson.html
.. py:module:: urandom
``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)
:noindex:
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
ways.
.. 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
``ure``
-------
Minimal regular expression library. Refer to the offical `MicroPython docs for ure`_.
.. _MicroPython docs for ure: http://docs.micropython.org/en/latest/library/ure.html
.. py:module:: ustruct
``ustruct``
-----------
Refer to the offical `MicroPython docs for ustruct`_.
.. _MicroPython docs for ustruct: http://docs.micropython.org/en/latest/library/ustruct.html
``utime``
---------
``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: https://github.com/micropython/micropython-lib
.. py:module:: collections
``collections``
---------------
Collections module.
.. py:module:: contextlib
``contextlib``
--------------
Contextlib module.
.. py:module:: functools
``functools``
-------------
Functools module.
.. py:module:: itertools
``itertools``
-------------
Itertools module.
.. warning::
:py:func:`itertools.tee` is not implemented correctly.
.. py:module:: string
``string``
----------
String module.
.. py:module:: struct
``struct``
----------
Struct module.
.. py:module:: uuid
``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``.
**Examples**:
.. code-block:: python
UUID('{12345678-1234-5678-1234-567812345678}')
UUID('12345678123456781234567812345678')
UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
UUID(bytes='\x12\x34\x56\x78' * 4)
UUID(int=0x12345678123456781234567812345678)
.. versionadded:: 1.10
.. py:attribute:: bytes
UUID as ``bytes()`` object
.. py:attribute:: node
Node of this UUID
.. py:attribute:: hex
Hex-String representation of this UUID
.. py:attribute:: version
UUID version accordiung to RFC 4122
.. py:function:: uuid4()
Generate a new UUID version 4 (random UUID).
.. versionadded:: 1.10
......@@ -8,26 +8,106 @@ CPython but wouldn't fit anywhere else in our implementation. Most
prominently, this is the :py:func:`utime.alarm` function for setting an RTC
alarm.
Like all other u-name modules, ``utime`` can also imported using the standard
``import time`` statement.
.. |time| replace:: ``time``
.. _time: https://docs.python.org/3/library/time.html
.. py:function:: utime.sleep(secs)
.. py:function:: sleep(secs)
Sleep for ``secs`` seconds. Can take a floating-point value.
.. py:function:: utime.sleep_ms(msecs)
.. py:function:: sleep_ms(msecs)
Sleep for ``msecs`` milliseconds. Only takes integer values.
.. py:function:: utime.sleep_us(usecs)
.. py:function:: sleep_us(usecs)
Sleep for ``usecs`` microseconds. Only takes integer values.
.. py:function:: utime.time()
.. py:function:: time()
Return the current timestamp in seconds since 2000-01-01 00:00 in
the local timezone.
.. py:function:: time_ms()
Return the current timestamp in milliseconds since 2000-01-01 00:00 in
the local timezone.
.. py:function:: monotonic()
Return a monotonically increasing timestamp.
.. versionadded:: 1.11
.. py:function:: monotonic_ms()
Return a monotonically increasing timestamp in milliseconds.
.. versionadded:: 1.11
.. py:function:: ticks_ms()
Return processor ticks (converted to milliseconds) since Pycardium startup.
This function should be the preferred method for timing and profiling
because it does not need an API call and thus is very fast.
.. versionadded:: 1.13
.. py:function:: ticks_us()
Return processor ticks (converted to microseconds) since Pycardium startup.
This function should be the preferred method for timing and profiling
because it does not need an API call and thus is very fast.
.. versionadded:: 1.13
.. py:function:: unix_time()
Return the current unix time as seconds since the epoch.
.. versionadded:: 1.12
.. py:function:: unix_time_ms()
Return the current unix time as milliseconds since the epoch.
.. versionadded:: 1.12
.. py:function:: set_time(secs)
Sets the time to ``secs`` seconds since 2000-01-01 00:00 in the local
timezone.
.. versionchanged:: 1.4
:py:func:`utime.set_time` previously applied a wrong timezone offset,
thus leading to wrong results.
.. py:function:: set_time_ms(msecs)
Set the time to ``msecs`` seconds since 2000-01-01 00:00 in the local
timezone.
.. versionadded:: 1.12
.. py:function:: set_unix_time(secs)
Sets the time to ``secs`` seconds since 1970-01-01 00:00 UTC.
This corresponds to a regular Unix timestamp which can be obtained
by running ``date +%s`` in a command line or ``int(time.time())``
in Python.
.. py:function:: set_unix_time_ms(msecs)
Set the time to ``msecs`` milliseconds since the unix epoch.
Return the current timestamp in seconds since 2000-01-01
.. versionadded:: 1.12
.. py:function:: utime.localtime([secs])
.. py:function:: localtime([secs])
Return the current time as a timestruct tuple. If ``secs`` is given, return
its timestruct tuple instead. Timestruct tuple looks like:
......@@ -37,14 +117,14 @@ alarm.
(year, month, mday, hour, min, sec, wday, yday)
# 0 1 2 3 4 5 6 7
.. py:function:: utime.mktime(t)
.. py:function:: mktime(t)
Convert timestruct tuple into a seconds time stamp. See
:py:func:`utime.localtime` for details about timestruct tuples.
:returns: Seconds since 2000-01-01
.. py:function:: utime.alarm(secs, [callback])
.. py:function:: alarm(secs, [callback])
Register the next RTC alarm for the timestamp ``secs``. ``secs`` is seconds
since 2000-01-01.
......@@ -58,13 +138,13 @@ alarm.
.. code-block:: python
import utime
import time
def minute_timer(x):
current = utime.time()
current = time.time()
print("Current: " + str(current))
alarm = (current // 60 + 1) * 60
utime.alarm(alarm, minute_timer)
time.alarm(alarm, minute_timer)
minute_timer(None)
......@@ -73,13 +153,13 @@ alarm.
.. code-block:: python
import interrupt, utime
import interrupt, time
def 5_second_timer(x):
current = utime.time()
current = time.time()
print("Current: " + str(current))
alarm = (current // 10) * 10 + 5
utime.alarm(alarm)
time.alarm(alarm)
# This time, we need to register and enable the callback manually
interrupt.set_callback(interrupt.RTC_ALARM, 5_second_timer)
......
.. py:module:: ws2812
``ws2812`` - Neopixel LEDs
==========================
The ``ws2812`` module controls LEDs of the WS2812 type. Just as the ``leds`` module, it exposes a function :py:func:`ws2812.set_all`, which works a similar fashion.
.. versionadded:: 1.10
.. py:function:: set_all(pin, colors)
Set multiple of the LEDs to RGB values.
Filling starts at the LED connected to the specified gpio pin.
:param int pin: ID of the pin to use for sending the data.
:param colors: List of RGB triplets.
**Example**
.. code-block:: python
import color, time, ws2812, gpio
gpio.set_mode(gpio.WRISTBAND_2, gpio.mode.OUTPUT)
i = 0
while True:
col1 = color.from_hsv(i % 360, 1.0, 0.1)
col2 = color.from_hsv((i + 20) % 360, 1.0, 0.1)
col3 = color.from_hsv((i + 40) % 360, 1.0, 0.1)
ws2812.set_all(gpio.WRISTBAND_2, [col1, col2, col3])
i += 1
time.sleep_ms(10)
.. versionadded:: 1.10
Documentation/static/bhi160-coordinates.png

324 KiB

.. _usb_file_transfer:
USB File Transfer
=================
The card10 badge bootloader offers a USB Mass Storage mode to access its 8MB external flash.
This flash contains a FAT32 filesystem and files on it will be visible to software running on the badge.
Getting to the USB mode
-----------------------
To get to the USB mode, you will need to boot the badge while keeping the bottom-right button pressed.
.. image:: static/bootloader-buttons.png
1. If the badge is on, hold the top-left (power) button until the sleep screen appears, then release.
2. Start holding the bottom-right button.
3. Quickly press and release the top-left (power) button to turn the badge on.
4. Your badge should now be in file transfer mode, and you can then release the bottom-right button.
If you succesfully got into USB File Transfer mode, the screen will display its version and notify about the USB mode by displaying ``USB activated. Ready.``. If you connect the badge via USB to your computer, it should now detect 8MB of flash storage that you can mount in the same way as a pendrive.
This pendrive can contain multiple files with different functions, some of them outlined here:
============== ========
File name Function
============== ========
``card10.bin`` Firmware update file for the badge. If this file is present, the bootloader will perform an internal update to boot from this firmware file, then it will be deleted.
``main.py`` This file contains the default `application` to be run on power on.
``menu.py`` This file contains the default `menu` to be run when the power button is short-pressed.
``*.py`` These are application files written in (Micro)Python that can be run from the menu.
``*.elf`` These are :ref:`l0dables` that can be run from the menu.
============== ========
Updating files and rebooting
----------------------------
No matter which file you are writing, the bootloader will display a red ``Writing`` status message while write operations are pending. Please wait until it displays ``Ready`` again before resetting the badge by pressing the power button again.
......@@ -6,31 +6,17 @@
#include "gfx.h"
#include "display.h"
/*
* "Decompress" splash-screen image. The algorithm works as follows:
*
* Each byte encodes up to 127 pixels in either white or black. The most
* significant bit determines the color, the remaining 7 bits determine the
* amount.
*/
static void bootloader_display_splash(void)
{
int idx = 0;
Color white = gfx_color(&display_screen, WHITE);
Color black = gfx_color(&display_screen, BLACK);
for (int i = 0; i < sizeof(splash); i++) {
Color color = (splash[i] & 0x80) ? white : black;
uint8_t length = splash[i] & 0x7f;
for (int j = 0; j < length; j++) {
uint16_t x = idx % 160;
uint16_t y = idx / 160;
gfx_setpixel(&display_screen, x, y, color);
idx++;
}
}
gfx_copy_region_rle_mono(
&display_screen,
0,
0,
160,
80,
sizeof(splash),
(const void *)(splash)
);
gfx_update(&display_screen);
}
......@@ -55,6 +41,21 @@ void bootloader_display_header(void)
bootloader_display_line(2, CARD10_VERSION, white);
}
void bootloader_display_error(char *errtype, char *line1, char *line2)
{
gfx_clear(&display_screen);
Color red = gfx_color(&display_screen, RED);
Color yellow = gfx_color(&display_screen, YELLOW);
Color white = gfx_color(&display_screen, WHITE);
bootloader_display_line(0, "[FATAL ERROR]", red);
bootloader_display_line(1, errtype, yellow);
bootloader_display_line(2, CARD10_VERSION, white);
bootloader_display_line(3, line1, white);
bootloader_display_line(4, line2, white);
}
/*
* Display a line of text on the display.
*/
......
......@@ -5,6 +5,7 @@
/* Display */
void bootloader_display_init(void);
void bootloader_display_header(void);
void bootloader_display_error(char *errtype, char *line1, char *line2);
void bootloader_display_line(int line, char *string, uint16_t color);
/* USB */
......
......@@ -6,8 +6,12 @@ BIN1="$2"
BIN2="$3"
BINOUT="$4"
dd if=/dev/zero ibs=1k count=448 2>/dev/null | LANG=C tr "\000" "\377" > "$BINOUT"
dd if="$BIN1" of="$BINOUT" conv=notrunc 2>/dev/null
dd if="$BIN2" >> "$BINOUT" 2>/dev/null
if [ "$(stat -c "%s" "${BIN1}")" -gt 589824 ]; then
echo "$0: ${BIN1} is too big to fit!" >&2
exit 1
fi
objcopy -I binary -O binary --pad-to=589824 --gap-fill=255 "${BIN1}" "$BINOUT"
cat "$BIN2" >>"$BINOUT"
"$PYTHON" "$(dirname "$0")/crc_patch.py" "$BINOUT"
#!/usr/bin/env python3
import sys
import crc16
import warnings
warnings.simplefilter("ignore")
try:
import crc16
crcfun = crc16.crc16xmodem
except ImportError:
try:
import crcmod
crcfun = crcmod.predefined.mkCrcFun("xmodem")
except ImportError:
try:
import crcelk
crcfun = crcelk.CRC_XMODEM.calc_bytes
except ImportError:
raise Exception(
"Could not find a CRC implementation. Tried: crc16, crcmod, crcelk."
)
def main():
data = open(sys.argv[1], 'rb').read()
crc = crc16.crc16xmodem(data)
data = open(sys.argv[1], "rb").read()
crc = crcfun(data)
# print(crc)
padded = data + bytes([crc >> 8, crc & 0xFF])
crc = crc16.crc16xmodem(padded)
crc = crcfun(padded)
# print(crc)
open(sys.argv[1], 'wb').write(padded)
open(sys.argv[1], "wb").write(padded)
if __name__ == "__main__":
......
......@@ -32,6 +32,24 @@
DIR dir;
FATFS FatFs;
int format(void)
{
BYTE work[FF_MAX_SS * 16];
/* Create FAT volume */
int res = f_mkfs("", FM_ANY | FM_SFD, 0, work, sizeof work);
if (res != FR_OK) {
printf("Failed to make new FS %d\n", res);
return -1;
}
f_setlabel("card10");
if (res != FR_OK) {
printf("Failed to set volume name %d\n", res);
return -1;
}
return 0;
}
int mount(void)
{
FRESULT res;
......@@ -161,6 +179,9 @@ void flash_partition(void)
data); /* wild cast. not sure if this works */
if (ret != E_NO_ERROR) {
printf("FLC_Write failed with %d\n", ret);
bootloader_display_error(
"Firmware Write", "Firmware not", "updated."
);
while (1)
;
}
......@@ -195,6 +216,19 @@ static void pmic_button(bool falling)
}
}
static void msc(void)
{
bootloader_display_header();
bootloader_display_line(3, "USB activated.", 0xffff);
bootloader_display_line(4, "Ready.", 0xffff);
run_usbmsc();
// If we return, don't try to boot. Maybe rather trigger a software reset.
// Reason: Not sure in which state the USB peripheral is and what kind
// of interrupts are active.
while (1)
;
}
/******************************************************************************/
int main(void)
{
......@@ -210,16 +244,7 @@ int main(void)
// If the button is pressed, we go into MSC mode.
if (PB_Get(3)) {
bootloader_display_header();
bootloader_display_line(3, "USB activated.", 0xffff);
bootloader_display_line(4, "Ready.", 0xffff);
run_usbmsc();
// If we return, don't try to boot. Maybe rather trigger a software reset.
// Reason: Not sure in which state the USB peripheral is and what kind
// of interrupts are active.
while (1)
;
msc();
}
if (mount() == 0) {
......@@ -244,6 +269,7 @@ int main(void)
);
erase_partition();
flash_partition();
f_unlink("card10.bin");
bootloader_display_line(
4, "Trying to boot", 0xffff
);
......@@ -251,14 +277,31 @@ int main(void)
printf("No update needed\n");
}
}
} else {
bootloader_display_header();
bootloader_display_line(
3, "Failed to mount filesystem", 0xffff
);
printf("Failed to mount the external flash\n");
bootloader_display_line(3, "Creating new filesystem", 0xffff);
printf("Creating new filesystem\n");
if (format() == 0) {
/* Drop into MSC after a reboot */
card10_reset();
} else {
bootloader_display_line(
3, "Failed to create new filesystem", 0xffff
);
printf("Feiled to create new filesystem\n");
/* Prevent bootloops */
while (1) {
}
}
}
bootloader_display_line(4, "Trying to boot", 0xffff);
/* Get the intital SP of the firmware. If it is 0xFFFFFFFF, no image has been
* flashed yet. Drop into MSC for initial flashing. */
if (*((uint32_t *)PARTITION_START) == 0xFFFFFFFF) {
printf("No valid image in flash\n");
msc();
}
printf("Trying to boot\n");
......
......@@ -4,7 +4,9 @@ set -xe
cd "$(dirname "$0")"
test -d build/ && rm -r build/
git submodule update --init ./lib/micropython
# Get external libs (MicroPython, tiny-AES-c, SHA256)
git submodule deinit --all
git submodule update --init ./lib
meson --cross-file card10-cross.ini build/ "$@"
set +x
......
......@@ -6,7 +6,7 @@ strip = 'arm-none-eabi-strip'
[properties]
c_args = ['-mthumb', '-mcpu=cortex-m4', '-mfloat-abi=softfp', '-mfpu=fpv4-sp-d16', '-Wa,-mimplicit-it=thumb', '-ffunction-sections', '-fdata-sections', '-fsingle-precision-constant', '-fno-isolate-erroneous-paths-dereference']
c_link_args = ['-mthumb', '-mcpu=cortex-m4', '-mfloat-abi=softfp', '-mfpu=fpv4-sp-d16', '-Wl,--start-group', '-lc', '-lnosys', '-Wl,--end-group', '--specs=nano.specs']
c_link_args = ['-mthumb', '-mcpu=cortex-m4', '-mfloat-abi=softfp', '-mfpu=fpv4-sp-d16', '-Wl,--start-group', '-lc', '-lnosys', '-Wl,--end-group', '--specs=nano.specs', '-Wl,-wrap,BbBleDrvRand']
target_defs = ['-DTARGET=32665', '-DTARGET_REV=0x4131', '-DBOARD_CARD10=1']
......
......@@ -18,9 +18,11 @@ in stdenv.mkDerivation rec {
bash
crc16
gcc-arm-embedded
git
meson
ninja
py
py.pkgs.pillow
];
src = ./.;
buildCommand = ''
......@@ -33,7 +35,7 @@ in stdenv.mkDerivation rec {
chmod -R +w .
# The nix sandbox does not have /usr/bin/env bash, patch things up.
for f in lib/micropython/*.sh; do
for f in lib/micropython/*.sh tools/*.sh; do
patchShebangs "$f"
done
......@@ -41,10 +43,13 @@ in stdenv.mkDerivation rec {
meson --cross-file card10-cross.ini "$build"
ninja -C "$build" -j $NIX_BUILD_CORES
# Copy artifacts to derivation outputs.
install -D -m 444 "$build/bootloader/bootloader.elf" -t "$out/bootloader"
install -D -m 444 "$build/pycardium/pycardium_epicardium.bin" -t "$out/pycardium"
install -D -m 444 "$build/epicardium/epicardium.elf" -t "$out/epicardium"
install -D -m 444 "$build/pycardium/pycardium.elf" -t "$out/pycardium"
# Copy ELFs for debugging
install -D -m 444 "$build/bootloader/bootloader.elf" -t "$out/lib/bootloader.elf"
install -D -m 444 "$build/epicardium/epicardium.elf" -t "$out/lib/epicardium.elf"
install -D -m 444 "$build/pycardium/pycardium.elf" -t "$out/lib/pycardium.elf"
# Create new flash contents
install -D -m 444 "$build/pycardium/pycardium_epicardium.bin" "$out/card10/card10.bin"
install -m 444 preload/*.py -t $out/card10/
cp -ar preload/apps $out/card10/
'';
}