Modules¶
Custom features exposed as Community Modules
Refer to QMK’s documentation for details on how to use this feature
allocator¶
Utilities to use custom allocators instead of stdlib’s implementation.
This is: malloc()
, free()
, calloc()
and realloc()
.
-
struct alloc_stats_t¶
[source] Information about an allocation.
-
allocator_t *allocator¶
[source] Allocator used to request this memory.
-
lifetime_t lifetime¶
[source] Allocation’s duration.
-
allocator_t *allocator¶
-
struct allocator_t¶
[source] Information about a custom allocator.
-
realloc_fn realloc¶
[source] Pointer to its
realloc
implementation.
-
realloc_fn realloc¶
Caution
These wrappers add some extra logic as well as calling allocator->function(args)
.
Use them instead of manually executing the functions.
-
void *malloc_with(allocator_t *allocator, size_t total_size)¶
[source] Run
malloc
’s implementation of the given allocator.
-
void free_with(allocator_t *allocator, void *ptr)¶
[source] Run
free
’s implementation of the given allocator.
-
void *calloc_with(allocator_t *allocator, size_t nmemb, size_t size)¶
[source] Run
calloc
’s implementation of the given allocator.
-
void *realloc_with(allocator_t *allocator, void *ptr, size_t size)¶
[source] Run
realloc
’s implementation of the given allocator.
-
const allocator_t **get_known_allocators(int8_t *n)¶
[source] Get a pointer to every allocator implementation.
n
will be set to the number of allocators.
-
const allocator_t *get_default_allocator(void)¶
[source] Get the allocator defined as “default”.
-
extern allocator_t ch_core_allocator¶
[source] ChibiOS’ core allocator.
-
allocator_t new_ch_pool_allocator(int *pool, const char *name)¶
[source] Create a new ChibiOS’ pool allocator.
-
allocator_t new_ch_heap_allocator(int *heap, const char *name)¶
[source] Create a new ChibiOS’ heap allocator.
arm_math_m0¶
Replaces some C builtins for floating point numbers (eg: sinf
) with optimized implementations for Cortex-M0 and M0+ cores.
crash¶
Utilities to check why (if) last execution crashed.
Warning
Only works on Cortex-M microcontrollers, but apparently, not on M4F.
dual_rp¶
Run code on the second core of your RP2040.
-
void c1_main(void)¶
[source] Entrypoint of the second core.
- Its default implementation is:
Wait for first core to setup ChibiOS
Run
c1_init_kb
andc1_init_user
In an endless loop, run
c1_main_kb
andc1_main_user
However, it is defined weakly, you can overwrite it.
Caution
If you do so, the functions mentioned above will no longer be called.
glitch_text¶
API to draw glitch text on QP screens.
-
struct glitch_text_state_t¶
[source] Information about a glitch text.
-
anim_phase_t phase¶
[source] Current animation phase.
-
callback_fn_t callback¶
[source] User-provided function used to render text.
-
anim_phase_t phase¶
-
int glitch_text_start(const char *text, callback_fn_t callback)¶
[source] Start glitch animation targeting the given text for each frame, callback gets invoked with the text to be rendered
- Parameters:
text – Target string (will be copied).
callback – Function executed each frame to render the new string.
Attention
Text can be at most 64 chars long.
- Return: Error code
0
: Color was found, and assigned into pointer.-EINVAL
: Invalid input.
indicators¶
Declaratively define RGB indicators.
Your configuration would look like:
const indicator_t PROGMEM indicators[] = {
LAYER_INDICATOR(UTILS, RGB_OFF),
KEYCODE_IN_LAYER_INDICATOR(QK_BOOT, UTILS, RGB_RED),
};
- Since indicators are checked (and applied) in the same order that you define them, this config is:
On the layer
UTILS
, all LEDs will be off except forQK_BOOT
which will be redNo indicator to be drawn on other layers (running effect left unchanged)
Hint
In general, you will use the convenience macros. However, you might need to manually instantiate these data structures to define custom conditions.
-
struct indicator_fn_args_t¶
[source] State about the LED being checked.
Used to tell whether the indicator’s color should be applied.
-
enum indicator_flags_t¶
[source] Different conditions to be checked
-
struct indicator_t¶
[source] An indicator’s specification:
-
indicator_flags_t flags¶
[source] Which conditions have to be checked.
-
indicator_fn_args_t conditions¶
[source] Values used to check (the
<X>
s above).
-
indicator_flags_t flags¶
-
KEYCODE_INDICATOR(_keycode, rgb)¶
[source] Indicator on any key mapped to the given keycode.
- Parameters:
_keycode – Value of the keycode.
rgb – Color to be applied.
-
LAYER_INDICATOR(_layer, rgb)¶
[source] Indicator for all LEDs in the given layer.
- Parameters:
_layer – Where the indicator should fire.
rgb – Color to be applied.
-
KEYCODE_IN_LAYER_INDICATOR(_keycode, _layer, rgb)¶
[source] Indicator on any key mapped to the given keycode in the given layer.
- Parameters:
_keycode – Value of the keycode.
_layer – Where the indicator should fire.
rgb – Color to be applied.
-
ASSIGNED_KEYCODE_IN_LAYER_INDICATOR(_layer, rgb)¶
[source] Indicator on any key that has been mapped in the given layer (ie: is not
KC_NO
norKC_TRNS
) .- Parameters:
_layer – Where the indicator should fire.
rgb – Color to be applied.
-
KEYCODE_WITH_MOD_INDICATOR(_keycode, mod_mask, rgb)¶
[source] Indicator on any key mapped to the given keycode while mods are active.
- Parameters:
_keycode – Value of the keycode.
mod_mask – Bitmask of the modifiers that must be active.
rgb – Color to be applied.
-
CUSTOM_KEYCODE_IN_LAYER_INDICATOR(_layer, rgb)¶
[source] Indicator on any key mapped to a custom keycode in the given layer.
- Parameters:
_layer – Where the indicator should fire.
rgb – Color to be applied.
-
bool draw_indicators(uint8_t led_min, uint8_t led_max)¶
[source] Check conditions, drawing the indicator if they met, for all leds in the given range.
- Parameters:
led_min – First LED to be drawn.
led_max – Last LED to be drawn.
Warning
Since QMK does not (yet?) allow to hook modules into the RGB system, you need to call this function from within
rgb_matrix_indicators_advanced_user
ledmap¶
Define a static, per-key, RGB matrix design.
It works similar to keymaps, mapping a color to each key and allowing transparency.
Your configuration would end up looking like:
const ledmap_color_t PROGMEM ledmap[][MATRIX_ROWS][MATRIX_COLS] = {
[_QWERTY] = LAYOUT(
RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED,
RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED,
RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED,
RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED,
RED, RED, RED, RED, BLACK, WHITE, RED, TRNS, RED, RED
),
[_FN] = LAYOUT(
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
CYAN, CYAN, CYAN, CYAN, CYAN, CYAN, CYAN, CYAN, CYAN, CYAN, CYAN, CYAN,
BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE,
ROSE, ROSE, ROSE, ROSE, ROSE, ROSE, ROSE, ROSE, ROSE, ROSE, ROSE, ROSE,
WHITE,WHITE,BLACK,TRNS, BLACK, BLACK, RED, TRNS, WHITE,WHITE
),
};
Warning
- Due to reusing
LAYOUT
macro to define the colors, implementation is not too flexible. Assumes existence of a LED under every key.
Does not support assigning colors to LEDs that aren’t under a key (eg: indicators or underglow)
It also hasn’t been exhaustively tested, there might be some problems.
- Result(rgb_t, int) rgb_at_ledmap_location(uint8_t layer, uint8_t row, uint8_t col)[source]
Retrieve the color assigned to a key in the ledmap (transparency gets applied).
- Parameters:
layer – Where to look at.
row – Electrical position of the key in the matrix.
col – Electrical position of the key in the matrix.
rgb – Where the value will be written.
- Returns:
- Result of the operation.
Ok(rgb): Color was retrieved. Use
unwrap()
to get the value.- Err(val): Something went wrong. Use
unwrap_err()
to get the value. Possible values: -EINVAL
: Some input was wrong.-ENODATA
:TRNS
on layer 0 -> Dont overwrite the existing effect.-ENOTSUP
: Unknown value read (not a value inledmap_color_t
).
- Err(val): Something went wrong. Use
-
void draw_ledmap(uint8_t led_min, uint8_t led_max)¶
[source] Assign their color to all leds in the given range.
- Parameters:
led_min – First LED to be drawn.
led_max – Last LED to be drawn.
Warning
Since QMK does not (yet?) allow to hook modules into the RGB system, you need to call this function from within
rgb_matrix_indicators_advanced_user
logging¶
Custom logging utilities, inspired by Python’s logging
module.
Note
Under the hood, this is just a wrapper on top of printf()
.
Default format for logging messages.
-
enum log_level_t¶
[source] Different level of severity. Used to filter out messages.
Warning
If you want to add a new one, it has to be the last element.
Hint
The logging()
function will apply an extra transformation to your input, based on a custom format.
Its specifiers being:
%LL
: The message’s level (long). Eg:DEBUG
.These strings are set in
level_str
.
%LS
: Print only the first char of the previous string. Eg:D
.%M
: The actual message created bymsg
and...
passed tologging()
. With its regular format.%T
: Current time, you can overridelog_time()
to hook it with a RTC or whatever.Default implementation is seconds since boot.
%%
: Write a literal%
.
For example, with format of [%LL] %T -- %M
, messages would look like: [DEBUG] 3s -- Formatted message
-
log_level_t get_logging_level(void)¶
[source] Get the current level. Messages with a lower severity are dropped.
-
void set_logging_level(log_level_t level)¶
[source] Change the current level.
-
void step_logging_level(bool increase)¶
[source] Increase (or decrease) by one the level.
The direction is based on
increase
.
Attention
From this point, the functions are mostly implementation details.
You, most likely, don’t need to know anything about them.
-
log_level_t get_current_message_level(void)¶
[source] Get the severity of the message being emitted.
This may be used by a
sendchar_func_t
internally.
ls0xx¶
Support for LS0XX displays (eg: nice!view), extracted from my (quite abandoned) PR.
Attention
Might contain some bug that I haven’t found yet. Please report if you find something.
Since this driver is not part of QMK’s codebase, some integrations won’t work, namely, the auto-flushing and the power on/off of (in)activity are not applied to this device.
-
painter_device_t qp_ls0xx_device_t_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, uint16_t spi_divisor, int spi_mode, void *buf)¶
[source] Create a new device handle.
- Parameters:
panel_width – Width of the display
panel_height – Height of the display
chip_select_pin – GPIO pin used for SPI chip select (CS)
spi_divisor – SPI divisor to use when communicating with the display
spi_mode – SPI mode to use when communicating with the display
buf – Address of the buffer where data will be stored
memory¶
Tiny memory-usage and address “identification” functions.
-
bool ptr_in_main_stack(const void *addr)¶
[source] Check if the input pointer belongs to the main stack.
-
bool ptr_in_process_stack(const void *addr)¶
[source] Check if the input pointer belongs to the process stack.
micropython¶
Embeds microypthon’s interpreter into your board
Since that’s not very useful by itself, a module is provided to hook into QMK APIs. Namely, you use: import qmk
To execute some code, store it as a string and feed it into the mp_embed_exec_str
function
Tip
Writing a C-string directly is not convenient (eg: no IntelliSense for suggestions/typo detection)
To circumvent that, you can write a regular .py
file, and then use elpekenin_userspace py2c <file.py>
to generate
the equivalent string in a standalone file, which you can later #include
You could also point your editor at the qmk
folder, and get auto-completion thanks to the .pyi
files in it
Important
In the future, I plan to integrate import ...
with QMK filesystem API (not a thing yet)
When (if) this happens, you would be able to run dynamic code, opposed to the current state, where you can only execute something defined as a const char*
at compile time
Available APIs are:
"""Utilities to interact with QMK from MicroPython."""
# ruff: noqa: F401
# the modules being imported dont really exist on the VM
# these imports are the result of having multiple `.c` files
# to organize the code (each one gets its own `.pyi` generated)
#
# this is: you can't `import qmk.keycode` nor `import _keycode`
# instead, you `import qmk` and use it as `qmk.keycode.foo()`
from . import _keycode as keycode
from . import _rgb as rgb
version: str
"""Version of QMK on which this firmware was built, as a raw string."""
version_info: tuple[int, int, int]
"""Version of QMK on which this firmware was built, as a (major, minor, patch) tuple."""
def get_highest_active_layer() -> int:
"""Get what the highest (currently active) layer is."""
def send_string(text: str, /) -> None:
"""Send a string over HID."""
def tap_code(kc: int, /) -> None:
"""Send a basic keycode over HID."""
rng¶
Generate (pseudo-)random numbers.
Note
This is just a convenience layer on top of lib8tion.h
right now,
but may use another source in the future.
-
void rng_set_seed(uint16_t seed)¶
[source] Set the seed for the RNG. eg: invoking it from
keyboard_post_init_user
before consuming RNG.Tip
- You can for example call this:
The reading on a floating ADC pin
The value on some uninitialized memory address (only good entropy on cold start)
Warning
Setting a constant value means the PRNG sequence will be the same on every restart.
rp_sdk_wrappers¶
Replaces several C builtins (eg: __clzsi2
) with optimized implementations provided in the ROM of RP2040
There are no hooks for user logic in this module because its only purpose is setting up such functions
Warning
To set this module up you need to define a custom linker script
This is due to Pico-SDK using a section to reference the functions required to configure these replacements
To do that, you can add this snippet at the end of the default linker script for RP2040 in ChibiOS
SECTIONS {
.preinit : ALIGN(4){
. = ALIGN(4);
__preinit_array_base__ = .;
KEEP(*(SORT(.preinit_array.*)))
KEEP(*(.preinit_array))
__preinit_array_end__ = .;
} > XTORS_FLASH AT > XTORS_FLASH_LMA
}
scrolling_text¶
API to draw scrolling text on QP screens.
-
deferred_token draw_scrolling_text(painter_device_t device, uint16_t x, uint16_t y, painter_font_handle_t font, const char *str, uint8_t n_chars, uint32_t delay)¶
[source] Start a scrolling text.
- Parameters:
device – Display in which to draw
x – Coordinates where to draw
y – Coordinates where to draw
font – Font to be used
str – Text to be written
n_chars – How many chars to be written at any time
delay – Time between animation steps (in ms)
Return: Token of the deferred executor taking care of drawing
-
deferred_token draw_scrolling_text_recolor(painter_device_t device, uint16_t x, uint16_t y, painter_font_handle_t font, const char *str, uint8_t n_chars, uint32_t delay, uint8_t hue_fg, uint8_t sat_fg, uint8_t val_fg, uint8_t hue_bg, uint8_t sat_bg, uint8_t val_bg)¶
[source] Start a scrolling text with custom colors.
- Parameters:
device – Display in which to draw
x – Coordinates where to draw
y – Coordinates where to draw
font – Font to be used
str – Text to be written
n_chars – How many chars to be written at any time
delay – Time between animation steps (in ms)
hue_fg – Foreground (font) color
sat_fg – Foreground (font) color
val_fg – Foreground (font) color
hue_bg – Background color
sat_bg – Background color
val_bg – Background color
Return: Token of the deferred executor taking care of drawing
string¶
Small utilities to work with text.
-
struct string_t¶
[source] “String builder” without heap (
malloc()
,realloc()
,free
) usage.Code using this API would look similar to:
// create a stack-based buffer, 50bytes long string_t str = str_new(50); // add text to it str_append(&str, "Hello"); str_append(&str, " world"); // display it printf("%.*s\n", str.used, str.ptr);
-
static inline string_t str_new(size_t n)¶
[source] Create a temporary
string_t
.Warning
This works on a VLA. If you need the value to outlive the function where it is declared, use
malloc
or your own buffer instead.
-
size_t str_available(string_t str)¶
[source] Find out how many bytes in the buffer are left to be used.
types¶
Result/Option types. Expresively express type of operations that can fail or return nothing.
-
ResultImpl(T, E)¶
[source] Define a new result type.
- Parameters:
T – The type of values.
E – The type of errors.
version¶
Adds QMK_MAJOR
, QMK_MINOR
and QMK_PATCH
macros to check for the version of QMK in which you are building.
These are available under #include "qmk_version.h"
.