Skip to content
Snippets Groups Projects
Forked from card10 / firmware
1534 commits behind the upstream repository.
pycardium-guide.rst 12.37 KiB

Pycardium Module Development

This is a step-by-step guide on augmenting Pycardium with new modules. These module are either written in Python or in C:

  • Python Modules: Python modules live in pycardium/modules/py and are pre-compiled and packed into Pycardium at build-time. Python modules are meant to be used for creating abstractions and helpers based on lower level functionality. The rationale is that it is easier to write pythonic modules in python instead of having to wrap all that in C code. Though care has to be taken as these modules can eat quite a lot of space.
  • C Modules: C modules allow MicroPython code to interface with the rest of the system or allow a much faster implementation of performance-critical code. For interfacing with card10, these modules are mostly meant to make use of the :ref:`Epicardium API <epicardium_api_overview>`.

Python Modules

Adding a new Python module

Add a file in pycardium/modules/py. The name of the file dictates the name of the module. Next, add you file to the list in pycardium/modules/py/meson.build to make the build-system aware of it. Rebuild, and you should see your module pop up in the list shown by

help("modules")

Size Consideration

Python modules can get quite big. If you want to know exact sizes, take a look at the output of

ls -lh build/pycardium/*@@frozen.c@*/

If your module contains some kind of big lookup-table or data-block, consider pushing that into external flash. You can then read the data using standard Python open() and if you need to decode it, use the ustruct or ujson module.

Creating a new C module

Module Source

Create a new file in pycardium/modules. The basic structure of a C module looks like this:

#include "py/obj.h"

/* Define a function in this module */
static mp_obj_t mp_example_hello(mp_obj_t number)
{
        int num = mp_obj_get_int(number);
        printf("Hello from example: %d\r\n", num);
        return mp_const_none;
}
/* Create an object for this function */
static MP_DEFINE_CONST_FUN_OBJ_1(example_hello_obj, mp_example_hello);

/* The globals table for this module */
static const mp_rom_map_elem_t example_module_globals_table[] = {
        {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example)},
        {MP_ROM_QSTR(MP_QSTR_hello), MP_ROM_PTR(&example_hello_obj)},
};
static MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table);

const mp_obj_module_t example_module = {
        .base    = {&mp_type_module},
        .globals = (mp_obj_dict_t*)&example_module_globals,
};

/* This is a special macro that will make MicroPython aware of this module */
/* clang-format off */
MP_REGISTER_MODULE(MP_QSTR_example, example_module, MODULE_EXAMPLE_ENABLED);