Skip to content

Commit

Permalink
Merge #19726
Browse files Browse the repository at this point in the history
19726:  mcufont: Initial addition of MCUFont package  r=aabadie a=bergzand

### Contribution description

This adds the MCUFont library as a package to RIOT. Only the decoder part has been packaged. I did not touch the font generation, so the test includes a manually compressed font created via the tooling included in the package.

The included patch files have been submitted as PR upstream in mcufont/mcufont#30

### Testing procedure

Run the test on Native or on any board, The output should be along the lines of:
```
2023-06-11 21:56:40,685 # Help: Press s to start test, r to print it is ready
s
2023-06-11 21:56:42,651 # START
2023-06-11 21:56:42,652 # main(): This is RIOT! (Version: 2023.07-devel-512-g49ee9-pr/mcufont)
2023-06-11 21:56:42,652 # Generated RIOT application: 'mcufont'
2023-06-11 21:56:42,653 #                                                                                                                                 |
2023-06-11 21:56:42,654 #                                                                                                                                 |
2023-06-11 21:56:42,694 #                   █  █                                                                                                          |
2023-06-11 21:56:42,695 #  █     █          █  █                  █████   █    ███   ███████  █                                                           |
2023-06-11 21:56:42,697 #  █     █          █  █                  █    █  █   █   █     █     █                                                           |
2023-06-11 21:56:42,737 #  █     █   ████   █  █   ████           █    █  █  █     █    █     █                                                           |
2023-06-11 21:56:42,739 #  █     █  ██  ██  █  █  ██  ██          █    █  █  █     █    █     █                                                           |
2023-06-11 21:56:42,740 #  ███████  █    █  █  █  █    █          █████   █  █     █    █     █                                                           |
2023-06-11 21:56:42,781 #  █     █  ██████  █  █  █    █          █   █   █  █     █    █     █                                                           |
2023-06-11 21:56:42,782 #  █     █  █       █  █  █    █          █    █  █  █     █    █                                                                 |
2023-06-11 21:56:42,783 #  █     █  ██   █  █  █  ██  ██  █       █    █  █   █   █     █     █                                                           |
2023-06-11 21:56:42,807 #  █     █   ████   █  █   ████   █       █     █ █    ███      █     █                                                           |
2023-06-11 21:56:42,807 # { "threads": [{ "name": "idle", "stack_size": 256, "stack_used": 220 }]}
2023-06-11 21:56:42,808 # { "threads": [{ "name": "main", "stack_size": 1280, "stack_used": 436 }]}
```


### Issues/PRs references

None

Co-authored-by: Koen Zandberg <koen@bergzand.net>
  • Loading branch information
bors[bot] and bergzand authored Aug 15, 2023
2 parents 210c4f4 + e2e9c0c commit 2bb9a00
Show file tree
Hide file tree
Showing 14 changed files with 965 additions and 0 deletions.
9 changes: 9 additions & 0 deletions pkg/mcufont/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2023 Koen Zandberg
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.

config PACKAGE_MCUFONT
bool "MCUFont"
depends on TEST_KCONFIG
9 changes: 9 additions & 0 deletions pkg/mcufont/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
PKG_NAME=mcufont
PKG_URL=https://github.com/mcufont/mcufont
PKG_VERSION=9f3aa41b231195e7b2b59f78d8f01d06460b6d35
PKG_LICENSE=MIT

include $(RIOTBASE)/pkg/pkg.mk

all:
$(QQ)"$(MAKE)" -C $(PKG_SOURCE_DIR)/decoder -f $(RIOTBASE)/Makefile.base MODULE=$(PKG_NAME)
1 change: 1 addition & 0 deletions pkg/mcufont/Makefile.include
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INCLUDES += -I$(PKGDIRBASE)/mcufont/decoder
22 changes: 22 additions & 0 deletions pkg/mcufont/doc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @defgroup pkg_mcufont MCUFont
* @ingroup pkg
* @brief MCUFont is a font compression, decompression and rendering library
* for use with microcontroller systems.
*
* # Introduction
*
* MCUFont is a stand-alone font compression, decompression and rendering
* library for use with microcontroller systems. On microcontrollers only
* decompression and rendering is supported, the compression part is written in
* C++ and is not supposed to be run on constrained devices.
*
* MCUFont supports high quality rendering of supplied fonts with kerning and
* anti-aliasing support. It does not support font scaling.
*
* # License
*
* Licensed under MIT.
*
* @see https://github.com/mcufont/mcufont
*/
3 changes: 3 additions & 0 deletions pkg/mcufont/mcufont.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MODULE = mcufont

include $(RIOTBASE)/Makefile.base
6 changes: 6 additions & 0 deletions tests/pkg/mcufont/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
include ../Makefile.pkg_common

USEPKG += mcufont
CFLAGS += -I$(CURDIR)/fonts

include $(RIOTBASE)/Makefile.include
4 changes: 4 additions & 0 deletions tests/pkg/mcufont/Makefile.board.dep
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Boards with a screen can use disp_dev
ifneq (,$(filter stm32f429i-disc% stm32f746g-disco stm32f7508-dk pinetime adafruit-clue adafruit-pybadge esp32-wrover-kit,$(BOARD)))
USEMODULE += disp_dev
endif
4 changes: 4 additions & 0 deletions tests/pkg/mcufont/Makefile.ci
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
atmega8 \
nucleo-l011k4 \
#
19 changes: 19 additions & 0 deletions tests/pkg/mcufont/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
mcufont
=======

The mcufont test application renders a string inside a pixel buffer after which
the pixel buffer is rendered using one ASCII Block symbol per pixel. This gives
a figlet-like effect.

A default black and white only font is included in this test. It has been
generated from the MCUFont tools and fonts.

When a display is present on the board with disp_dev support, the text string is
also shown on the display. In that case another font with aliasing support is
included in the build. This adds about 10 KiB to the build (including the
display driver)

Usage
=====

Compile the application and run the test.
421 changes: 421 additions & 0 deletions tests/pkg/mcufont/fonts/DejaVuSans12.c

Large diffs are not rendered by default.

250 changes: 250 additions & 0 deletions tests/pkg/mcufont/fonts/DejaVuSans12bw.c

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions tests/pkg/mcufont/fonts/fonts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef FONTS_H
#define FONTS_H

#ifdef __cplusplus
extern "C" {
#endif

#include "DejaVuSans12bw.c"
#include "DejaVuSans12.c"

#ifdef __cplusplus
}
#endif

#endif /* FONTS_H */
168 changes: 168 additions & 0 deletions tests/pkg/mcufont/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* Copyright (C) 2023 Koen Zandberg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @ingroup tests
* @{
*
* @file
* @brief Test application for the MCUFont package
*
* @author Koen Zandberg <koen@bergzand.net>
*
* @}
*/

#include <stdio.h>
#include <string.h>
#include "mcufont.h"
#include "disp_dev.h"
#include "byteorder.h"

#define ENABLE_DEBUG 0
#include "debug.h"

#ifdef MODULE_DISP_DEV
#ifdef LCD_SCREEN_WIDTH
#define DISPLAY_BUFFER_MAX_SIZE (LCD_SCREEN_WIDTH)
#else
#define DISPLAY_BUFFER_MAX_SIZE (320)
#endif
static uint16_t display_buffer[DISPLAY_BUFFER_MAX_SIZE] = { 0 };
#endif

#define PIXBUF_NUM_ROWS 15
#define PIXBUF_NUM_COLS 16
#define PIXBUF_ALPHA_THRESHOLD 80

#define MCUFONT_FIG_TEST_FONT mf_rlefont_DejaVuSans12bw
#define MCUFONT_DISP_TEST_FONT mf_rlefont_DejaVuSans12

extern const struct mf_rlefont_s MCUFONT_FIG_TEST_FONT;
extern const struct mf_rlefont_s MCUFONT_DISP_TEST_FONT;

static const char input[] = "Hello, RIOT!";
static uint8_t fig_buf[PIXBUF_NUM_ROWS][PIXBUF_NUM_COLS] = { 0 };

static disp_dev_reg_t *init_display(void)
{
disp_dev_reg_t *disp_dev = NULL;
#ifdef MODULE_DISP_DEV
/* Use the first screen */
disp_dev = disp_dev_reg_find_screen(0);
if (!disp_dev) {
puts("No screen found!");
return NULL;
}
disp_dev_backlight_on();

/* Clear the screen */
disp_dev_area_t area;
for (uint16_t y = 0; y < disp_dev_height(disp_dev->dev); y ++) {
area.x1 = 0;
area.x2 = disp_dev_width(disp_dev->dev) - 1;
area.y1 = area.y2 = y;
disp_dev_map(disp_dev->dev, &area, display_buffer);
}
#endif
return disp_dev;
}

static void fig_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state)
{
(void)state;
DEBUG("[draw] x: %"PRIi16", y: %"PRIi16", count: %u, color: %u\n", x, y, count, alpha);
if (y >= PIXBUF_NUM_ROWS || ((x + count) >= (PIXBUF_NUM_COLS * 8))) {
return;
}
while (count--) {
uint8_t bitpos = x % 8;
uint8_t bytepos = x / 8;
if (alpha > PIXBUF_ALPHA_THRESHOLD) {
fig_buf[y][bytepos] |= (1 << (7 - bitpos));
}
x++;
}
}

static uint16_t _alpha2rgb(uint8_t alpha)
{
/* Assumes RGB 565 */
return (alpha / 8) | ((alpha / 7) << 5) | ((alpha / 8) << 11);
}

static void disp_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *disp)
{
DEBUG("[disp_draw] x: %"PRIi16", y: %"PRIi16", count: %u, color: %u\n", x, y, count, alpha);
while (count--) {
uint16_t color = htons(_alpha2rgb(alpha));
disp_dev_area_t area = {
.x1 = x,
.y1 = y,
.x2 = x,
.y2 = y,
};
disp_dev_map(disp, &area, &color);
x++;
}
}

static void print_fig_buf(void)
{
for (size_t y = 0; y < PIXBUF_NUM_ROWS; y++) {
for (size_t x = 0; x < PIXBUF_NUM_COLS; x++) {
for (int bitpos = 7; bitpos >= 0; bitpos--) {
if (fig_buf[y][x] & (1 << bitpos)) {
printf("█");
}
else {
printf(" ");
}
}
}
puts("");
}
}

static uint8_t char_callback(int16_t x0, int16_t y0, mf_char character, void *state)
{
return mf_render_character(&MCUFONT_FIG_TEST_FONT.font, x0, y0, character, &fig_callback, state);
}

static uint8_t disp_char_callback(int16_t x0, int16_t y0, mf_char character, void *state)
{
return mf_render_character(&MCUFONT_DISP_TEST_FONT.font, x0, y0, character, &disp_callback, state);
}

int main(void)
{
puts("mcufont package test application");
mf_render_aligned(
&MCUFONT_FIG_TEST_FONT.font,
0, 0,
MF_ALIGN_LEFT,
input, strlen(input),
&char_callback, NULL);

print_fig_buf();

if (IS_ACTIVE(MODULE_DISP_DEV)) {
disp_dev_reg_t *display = init_display();
puts("mcufont package test application");
int16_t width = mf_get_string_width(&MCUFONT_DISP_TEST_FONT.font, input, 0, true);
mf_render_aligned(
&MCUFONT_DISP_TEST_FONT.font,
(disp_dev_width(display->dev) - width) / 2,
(disp_dev_height(display->dev) - MCUFONT_DISP_TEST_FONT.font.line_height) / 2,
MF_ALIGN_LEFT,
input, strlen(input),
&disp_char_callback, display->dev);
}

return 0;
}
34 changes: 34 additions & 0 deletions tests/pkg/mcufont/tests/01-run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env python3

# Copyright (C) 2023 Koen Zandberg
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.

import sys
from testrunner import run

FONT_RENDER = """
█ █
█ █ █ █ █████ █ ███ ███████ █
█ █ █ █ █ █ █ █ █ █ █
█ █ ████ █ █ ████ █ █ █ █ █ █ █
█ █ ██ ██ █ █ ██ ██ █ █ █ █ █ █ █
███████ █ █ █ █ █ █ █████ █ █ █ █ █
█ █ ██████ █ █ █ █ █ █ █ █ █ █ █
█ █ █ █ █ █ █ █ █ █ █ █ █
█ █ ██ █ █ █ ██ ██ █ █ █ █ █ █ █ █
█ █ ████ █ █ ████ █ █ █ █ ███ █ █
"""


def testfunc(child):
for line in FONT_RENDER.splitlines():
child.expect_exact(line)
print("\nSUCCESS")


if __name__ == "__main__":
sys.exit(run(testfunc))

0 comments on commit 2bb9a00

Please sign in to comment.