diff --git a/pkg/Kconfig b/pkg/Kconfig index 81ff5332af..89a3c50cea 100644 --- a/pkg/Kconfig +++ b/pkg/Kconfig @@ -32,6 +32,7 @@ rsource "nanocbor/Kconfig" rsource "nanopb/Kconfig" rsource "qcbor/Kconfig" rsource "qDSA/Kconfig" +rsource "qr-code-generator/Kconfig" rsource "relic/Kconfig" rsource "semtech-loramac/Kconfig" rsource "talking_leds/Kconfig" diff --git a/pkg/qr-code-generator/Kconfig b/pkg/qr-code-generator/Kconfig new file mode 100644 index 0000000000..d0b3f13503 --- /dev/null +++ b/pkg/qr-code-generator/Kconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2021 Inria +# +# 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_QR-CODE-GENERATOR + bool "QR Code generator" + depends on TEST_KCONFIG diff --git a/pkg/qr-code-generator/Makefile b/pkg/qr-code-generator/Makefile new file mode 100644 index 0000000000..4b98f0c475 --- /dev/null +++ b/pkg/qr-code-generator/Makefile @@ -0,0 +1,11 @@ +PKG_NAME=qr-code-generator +PKG_URL=https://github.com/nayuki/QR-Code-generator +PKG_VERSION=71c75cfeb0f06788ebc43a39b704c39fcf5eba7c # v1.6.0 +PKG_LICENSE=MIT + +include $(RIOTBASE)/pkg/pkg.mk + +CFLAGS += -Wno-type-limits + +all: + $(QQ)"$(MAKE)" -C $(PKG_SOURCE_DIR)/c -f $(CURDIR)/$(PKG_NAME).mk diff --git a/pkg/qr-code-generator/Makefile.include b/pkg/qr-code-generator/Makefile.include new file mode 100644 index 0000000000..ab90976c68 --- /dev/null +++ b/pkg/qr-code-generator/Makefile.include @@ -0,0 +1 @@ +INCLUDES += -I$(PKGDIRBASE)/qr-code-generator/c diff --git a/pkg/qr-code-generator/doc.txt b/pkg/qr-code-generator/doc.txt new file mode 100644 index 0000000000..0365fb36e9 --- /dev/null +++ b/pkg/qr-code-generator/doc.txt @@ -0,0 +1,11 @@ +/** + * @defgroup pkg_qr-code-generator QR Code generator + * @ingroup pkg + * @brief QR Code generator library + * + * # License + * + * Licensed under MIT. + * + * @see https://github.com/nayuki/QR-Code-generator + */ diff --git a/pkg/qr-code-generator/qr-code-generator.mk b/pkg/qr-code-generator/qr-code-generator.mk new file mode 100644 index 0000000000..6b0a0c8af5 --- /dev/null +++ b/pkg/qr-code-generator/qr-code-generator.mk @@ -0,0 +1,5 @@ +MODULE = qr-code-generator + +SRC := qrcodegen.c + +include $(RIOTBASE)/Makefile.base diff --git a/tests/pkg_qr-code-generator/Kconfig b/tests/pkg_qr-code-generator/Kconfig new file mode 100644 index 0000000000..db88101391 --- /dev/null +++ b/tests/pkg_qr-code-generator/Kconfig @@ -0,0 +1,11 @@ +config APPLICATION + bool + default y + imply MODULE_AUTO_INIT_SCREEN if BOARD_HAS_DISPLAY + imply MODULE_DISP_DEV if BOARD_HAS_DISPLAY + depends on TEST_KCONFIG + +config BOARD_HAS_DISPLAY + bool + default y + depends on BOARD_PINETIME || BOARD_ADAFRUIT_CLUE || BOARD_STM32F429I_DISC1 || BOARD_STM32F429I_DISCO diff --git a/tests/pkg_qr-code-generator/Makefile b/tests/pkg_qr-code-generator/Makefile new file mode 100644 index 0000000000..f728b51e4a --- /dev/null +++ b/tests/pkg_qr-code-generator/Makefile @@ -0,0 +1,13 @@ +include ../Makefile.tests_common + +USEPKG += qr-code-generator + +MESSAGE_TO_ENCODE ?= "https://riot-os.org" + +CFLAGS += -DMESSAGE_TO_ENCODE=\"$(MESSAGE_TO_ENCODE)\" + +# This application provides a 'Kconfig' file and we want to explicitly disable +# Kconfig by default by setting this variable to empty +SHOULD_RUN_KCONFIG ?= + +include $(RIOTBASE)/Makefile.include diff --git a/tests/pkg_qr-code-generator/Makefile.board.dep b/tests/pkg_qr-code-generator/Makefile.board.dep new file mode 100644 index 0000000000..7a9d1586e5 --- /dev/null +++ b/tests/pkg_qr-code-generator/Makefile.board.dep @@ -0,0 +1,5 @@ +# Boards with a screen can use disp_dev +ifneq (,$(filter stm32f429i-disc% pinetime adafruit-clue,$(BOARD))) + USEMODULE += auto_init_screen + USEMODULE += disp_dev +endif diff --git a/tests/pkg_qr-code-generator/app.config.test b/tests/pkg_qr-code-generator/app.config.test new file mode 100644 index 0000000000..105f736641 --- /dev/null +++ b/tests/pkg_qr-code-generator/app.config.test @@ -0,0 +1 @@ +CONFIG_PACKAGE_QR-CODE-GENERATOR=y diff --git a/tests/pkg_qr-code-generator/main.c b/tests/pkg_qr-code-generator/main.c new file mode 100644 index 0000000000..8202dbc8e2 --- /dev/null +++ b/tests/pkg_qr-code-generator/main.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2021 Inria + * + * 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 qr-code-generator package + * + * @author Alexandre Abadie + * + * @} + */ + +#include + +#include +#include +#include "qrcodegen.h" + +#ifdef MODULE_DISP_DEV +#include "disp_dev.h" +#endif + +#ifndef MESSAGE_TO_ENCODE +#define MESSAGE_TO_ENCODE "unknown" +#endif + +static uint8_t qr0[qrcodegen_BUFFER_LEN_FOR_VERSION(2)]; +static uint8_t buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(2)]; + +int main(void) +{ + if (!qrcodegen_encodeText(MESSAGE_TO_ENCODE, + buffer, qr0, qrcodegen_Ecc_MEDIUM, + qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, + qrcodegen_Mask_AUTO, true)) { + puts("Encoding error"); + return -1; + } + + int size = qrcodegen_getSize(qr0); + +#ifdef MODULE_DISP_DEV + /* Use the first screen */ + disp_dev_reg_t *disp_dev = disp_dev_reg_find_screen(0); + if (!disp_dev) { + puts("No screen found!"); + return -1; + } + disp_dev_backlight_on(); + + uint16_t white = UINT16_MAX; + uint16_t black = 0; + for (uint16_t y = 0; y < disp_dev_height(disp_dev->dev); y++) { + for (uint16_t x = 0; x < disp_dev_width(disp_dev->dev); x++) { + disp_dev_map(disp_dev->dev, x, x, y, y, &black); + } + } + + const uint8_t scale = disp_dev_height(disp_dev->dev) / size; + const uint8_t w_offset = (disp_dev_width(disp_dev->dev) - (size * scale)) / 2; + const uint8_t h_offset = (disp_dev_height(disp_dev->dev) - (size * scale)) / 2; +#endif + + for (int y = 0; y < size; y++) { + for (int x = 0; x < size; x++) { +#ifdef MODULE_DISP_DEV + for (int w = x * scale; w < (x + 1) * scale; w++) { + for (int h = y * scale; h < (y + 1) * scale; h++) { + if (qrcodegen_getModule(qr0, x, y)) { + disp_dev_map(disp_dev->dev, + w + w_offset, w + w_offset, h + h_offset, h + h_offset, + &white); + } + } + } +#endif + printf("%s", qrcodegen_getModule(qr0, x, y) ? "██" : " "); + + } + puts(""); + } + + return 0; +} diff --git a/tests/pkg_qr-code-generator/tests/01-run.py b/tests/pkg_qr-code-generator/tests/01-run.py new file mode 100755 index 0000000000..d3961f6a21 --- /dev/null +++ b/tests/pkg_qr-code-generator/tests/01-run.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2021 Inria +# +# 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 + + +QR_CODE = ( + "██████████████ ██████████ ██ ██████████████\n" + "██ ██ ██ ██ ████ ██ ██\n" + "██ ██████ ██ ████ ██ ████ ██ ██████ ██\n" + "██ ██████ ██ ████ ██ ██ ██████ ██\n" + "██ ██████ ██ ██████████ ████ ██ ██████ ██\n" + "██ ██ ██ ██ ████ ██ ██\n" + "██████████████ ██ ██ ██ ██ ██ ██████████████\n" + " ██ ██████ ██ \n" + " ████ ██ ████ ██████ ██████ ██ ██████████\n" + " ████ ██ ████████ ██ ████ ██\n" + " ██ ████████ ██ ██ ████ ██████\n" + "██████ ██ ██ ██ ██ ██ ██ \n" + " ████████ ██ ██ ██████ ██ ████\n" + " ██ ████ ██ ██ ██████ ██ ██\n" + "██ ██ ██ ████████ ██ ██ ██████\n" + " ██ ████ ████ ██ ██ ██ ██ ██ \n" + "██ ██ ██████ ████████████████ \n" + " ██████ ██ ████ ████ ████\n" + "██████████████ ████████ ████████ ██ ████ ████\n" + "██ ██ ██ ██████ ██ ████ ██\n" + "██ ██████ ██ ██████████ ████████████ ██\n" + "██ ██████ ██ ████ ██ ██ ████████ \n" + "██ ██████ ██ ██ ████ ██ ██ ██ ██\n" + "██ ██ ████ ██████████ ████ ██ \n" + "██████████████ ██ ██ ████ ████\n" +) + + +def testfunc(child): + for line in QR_CODE.split("\n"): + child.expect_exact(line) + print("\nSUCCESS") + + +if __name__ == "__main__": + sys.exit(run(testfunc))