zdsp: Add Q value print formatting helpers for
Introduce PRI style formatting for DSP values. These require the use of another separate macro to set up the argument (PRIq_arg). Signed-off-by: Yuval Peress <peress@google.com>
This commit is contained in:
parent
a55d7eefef
commit
acc5501118
6 changed files with 250 additions and 0 deletions
|
@ -38,6 +38,8 @@
|
|||
|
||||
#include <zephyr/dsp/basicmath.h>
|
||||
|
||||
#include <zephyr/dsp/print_format.h>
|
||||
|
||||
#include "zdsp_backend.h"
|
||||
|
||||
#endif /* INCLUDE_ZEPHYR_DSP_DSP_H_ */
|
||||
|
|
66
include/zephyr/dsp/print_format.h
Normal file
66
include/zephyr/dsp/print_format.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* Copyright (c) 2023 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_ZEPHYR_DSP_PRINT_FORMAT_H
|
||||
#define ZEPHYR_INCLUDE_ZEPHYR_DSP_PRINT_FORMAT_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <zephyr/dsp/types.h>
|
||||
|
||||
/**
|
||||
* @ingroup math_dsp
|
||||
* @defgroup math_printing Helper macros for printing Q values.
|
||||
*
|
||||
* Extends the existing inttypes headers for print formatting. Useage:
|
||||
* @code{c}
|
||||
* printk("Value=%" PRIq "\n", PRIq_arg(value, 6, 2));
|
||||
* @endcode
|
||||
*
|
||||
* For a Q value representing 0.5, the expected output will be:
|
||||
* "Value=2.000000"
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Insert Q value format string
|
||||
*/
|
||||
#define PRIq(precision) "s%" PRIu32 ".%0" STRINGIFY(precision) PRIu32
|
||||
|
||||
static inline int64_t ___PRIq_arg_shift(int64_t q, int shift)
|
||||
{
|
||||
if (shift < 0) {
|
||||
return llabs(q) >> -shift;
|
||||
} else {
|
||||
return llabs(q) << shift;
|
||||
}
|
||||
}
|
||||
|
||||
#define __EXP2(a, b) a ## b
|
||||
#define __EXP(a, b) __EXP2(a ## e, b)
|
||||
#define __CONSTPOW(C, x) __EXP(C, x)
|
||||
|
||||
#define __PRIq_arg_shift(q, shift) ___PRIq_arg_shift(q, ((shift) + (8 * (4 - (int)sizeof(q)))))
|
||||
#define __PRIq_arg_get(q, shift, h, l) FIELD_GET(GENMASK64(h, l), __PRIq_arg_shift(q, shift))
|
||||
#define __PRIq_arg_get_int(q, shift) __PRIq_arg_get(q, shift, 63, 31)
|
||||
#define __PRIq_arg_get_frac(q, precision, shift) \
|
||||
((__PRIq_arg_get(q, shift, 30, 0) * __CONSTPOW(1, precision)) / INT32_MAX)
|
||||
|
||||
/**
|
||||
* @brief Insert Q value arguments to print format
|
||||
*
|
||||
* @param[in] q The q value
|
||||
* @param[in] precision Number of decimal points to print
|
||||
* @param[in] shift The "scale" to shift @p q by
|
||||
*/
|
||||
#define PRIq_arg(q, precision, shift) \
|
||||
((q) < 0 ? "-" : ""), (uint32_t)__PRIq_arg_get_int(q, shift), \
|
||||
(uint32_t)__PRIq_arg_get_frac(q, precision, shift)
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_ZEPHYR_DSP_PRINT_FORMAT_H */
|
8
tests/subsys/dsp/print_format/CMakeLists.txt
Normal file
8
tests/subsys/dsp/print_format/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2023 Google LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(zdsp_conversions)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
5
tests/subsys/dsp/print_format/prj.conf
Normal file
5
tests/subsys/dsp/print_format/prj.conf
Normal file
|
@ -0,0 +1,5 @@
|
|||
CONFIG_ZTEST=y
|
||||
CONFIG_ZTEST_NEW_API=y
|
||||
CONFIG_NEWLIB_LIBC=y
|
||||
CONFIG_DSP=y
|
||||
CONFIG_CMSIS_DSP=y
|
161
tests/subsys/dsp/print_format/src/main.c
Normal file
161
tests/subsys/dsp/print_format/src/main.c
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* Copyright (c) 2023 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/dsp/print_format.h>
|
||||
#include <zephyr/ztest.h>
|
||||
#include <string.h>
|
||||
|
||||
#define float_multiplier(type) ((INT64_C(1) << (8 * sizeof(type) - 1)) - 1)
|
||||
|
||||
#define assert_strings(expected, actual) \
|
||||
zexpect_equal(strlen(expected), strlen(actual), "Expected %d(%s), got %d(%s)", \
|
||||
strlen(expected), expected, strlen(actual), actual); \
|
||||
zexpect_mem_equal(expected, actual, MIN(strlen(expected), strlen(actual)), \
|
||||
"Expected '%s', got '%s'", expected, actual)
|
||||
|
||||
ZTEST_SUITE(zdsp_print_format, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
ZTEST(zdsp_print_format, test_print_q31_precision_positive)
|
||||
{
|
||||
char buffer[256];
|
||||
q31_t q = (q31_t)0x0f5c28f0; /* 0.119999997 */
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(6), PRIq_arg(q, 6, 0));
|
||||
assert_strings("0.119999", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(6), PRIq_arg(q, 6, 1));
|
||||
assert_strings("0.239999", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(6), PRIq_arg(q, 6, -2));
|
||||
assert_strings("0.029999", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 0));
|
||||
assert_strings("0.1199", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 1));
|
||||
assert_strings("0.2399", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, -2));
|
||||
assert_strings("0.0299", buffer);
|
||||
}
|
||||
|
||||
ZTEST(zdsp_print_format, test_print_q31_precision_negative)
|
||||
{
|
||||
char buffer[256];
|
||||
q31_t q = (q31_t)0x83d70a00; /* -0.970000029 */
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(6), PRIq_arg(q, 6, 0));
|
||||
assert_strings("-0.970000", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(6), PRIq_arg(q, 6, 1));
|
||||
assert_strings("-1.940000", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(6), PRIq_arg(q, 6, -2));
|
||||
assert_strings("-0.242500", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 0));
|
||||
assert_strings("-0.9700", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 1));
|
||||
assert_strings("-1.9400", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, -2));
|
||||
assert_strings("-0.2425", buffer);
|
||||
}
|
||||
|
||||
ZTEST(zdsp_print_format, test_print_q15_precision_positive)
|
||||
{
|
||||
char buffer[256];
|
||||
q15_t q = (q15_t)0x28f5; /* 0.319986672 */
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(5), PRIq_arg(q, 5, 0));
|
||||
assert_strings("0.31997", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(5), PRIq_arg(q, 5, 1));
|
||||
assert_strings("0.63995", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(5), PRIq_arg(q, 5, -2));
|
||||
assert_strings("0.07999", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(3), PRIq_arg(q, 3, 0));
|
||||
assert_strings("0.319", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(3), PRIq_arg(q, 3, 1));
|
||||
assert_strings("0.639", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(3), PRIq_arg(q, 3, -2));
|
||||
assert_strings("0.079", buffer);
|
||||
}
|
||||
|
||||
ZTEST(zdsp_print_format, test_print_q15_precision_negative)
|
||||
{
|
||||
char buffer[256];
|
||||
q15_t q = (q15_t)0xc4bd; /* -0.462965789 */
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(5), PRIq_arg(q, 5, 0));
|
||||
assert_strings("-0.46298", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(5), PRIq_arg(q, 5, 1));
|
||||
assert_strings("-0.92596", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(5), PRIq_arg(q, 5, -2));
|
||||
assert_strings("-0.11574", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(3), PRIq_arg(q, 3, 0));
|
||||
assert_strings("-0.462", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(3), PRIq_arg(q, 3, 1));
|
||||
assert_strings("-0.925", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(3), PRIq_arg(q, 3, -2));
|
||||
assert_strings("-0.115", buffer);
|
||||
}
|
||||
|
||||
ZTEST(zdsp_print_format, test_print_q7_precision_positive)
|
||||
{
|
||||
char buffer[256];
|
||||
q7_t q = (q7_t)0x01; /* 0.007874016 */
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 0));
|
||||
assert_strings("0.0078", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 1));
|
||||
assert_strings("0.0156", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, -2));
|
||||
assert_strings("0.0019", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(2), PRIq_arg(q, 2, 0));
|
||||
assert_strings("0.00", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(2), PRIq_arg(q, 2, 1));
|
||||
assert_strings("0.01", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(2), PRIq_arg(q, 2, -2));
|
||||
assert_strings("0.00", buffer);
|
||||
}
|
||||
|
||||
ZTEST(zdsp_print_format, test_print_q7_precision_negative)
|
||||
{
|
||||
char buffer[256];
|
||||
q7_t q = (q7_t)0xe2; /* -0.228346457 */
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 0));
|
||||
assert_strings("-0.2343", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 1));
|
||||
assert_strings("-0.4687", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, -2));
|
||||
assert_strings("-0.0585", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(2), PRIq_arg(q, 2, 0));
|
||||
assert_strings("-0.23", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(2), PRIq_arg(q, 2, 1));
|
||||
assert_strings("-0.46", buffer);
|
||||
|
||||
snprintf(buffer, 256, "%" PRIq(2), PRIq_arg(q, 2, -2));
|
||||
assert_strings("-0.05", buffer);
|
||||
}
|
8
tests/subsys/dsp/print_format/testcase.yaml
Normal file
8
tests/subsys/dsp/print_format/testcase.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2023 Google LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
tests:
|
||||
zdsp.print_format:
|
||||
filter: TOOLCHAIN_HAS_NEWLIB == 1 or CONFIG_ARCH_POSIX
|
||||
tags: zdsp
|
||||
min_flash: 128
|
||||
min_ram: 64
|
Loading…
Add table
Add a link
Reference in a new issue