Line data Source code
1 0 : /* Copyright (c) 2023 Google LLC
2 : * SPDX-License-Identifier: Apache-2.0
3 : */
4 :
5 : #ifndef ZEPHYR_INCLUDE_DSP_PRINT_FORMAT_H_
6 : #define ZEPHYR_INCLUDE_DSP_PRINT_FORMAT_H_
7 :
8 : #include <inttypes.h>
9 : #include <stdlib.h>
10 : #include <zephyr/dsp/types.h>
11 :
12 : /**
13 : * @ingroup math_dsp
14 : * @defgroup math_printing Helper macros for printing Q values.
15 : *
16 : * Extends the existing inttypes headers for print formatting. Usage:
17 : * @code{c}
18 : * printk("Value=%" PRIq "\n", PRIq_arg(value, 6, 2));
19 : * @endcode
20 : *
21 : * For a Q value representing 0.5, the expected output will be:
22 : * "Value=2.000000"
23 : *
24 : * @{
25 : */
26 :
27 : /**
28 : * @brief Insert Q value format string
29 : */
30 1 : #define PRIq(precision) "s%" PRIu32 ".%0" STRINGIFY(precision) PRIu32
31 :
32 : static inline int64_t ___PRIq_arg_shift(int64_t q, int shift)
33 : {
34 : if (shift < 0) {
35 : return llabs(q) >> -shift;
36 : } else {
37 : return llabs(q) << shift;
38 : }
39 : }
40 :
41 : #define __EXP2(a, b) a ## b
42 : #define __EXP(a, b) __EXP2(a ## e, b)
43 : #define __CONSTPOW(C, x) __EXP(C, x)
44 :
45 : #define __PRIq_arg_shift(q, shift) ___PRIq_arg_shift(q, ((shift) + (8 * (4 - (int)sizeof(q)))))
46 : #define __PRIq_arg_get(q, shift, h, l) FIELD_GET(GENMASK64(h, l), __PRIq_arg_shift(q, shift))
47 : #define __PRIq_arg_get_int(q, shift) __PRIq_arg_get(q, shift, 63, 31)
48 : #define __PRIq_arg_get_frac(q, precision, shift) \
49 : ((__PRIq_arg_get(q, shift, 30, 0) * __CONSTPOW(1, precision)) / INT32_MAX)
50 :
51 : /**
52 : * @brief Insert Q value arguments to print format
53 : *
54 : * @param[in] q The q value
55 : * @param[in] precision Number of decimal points to print
56 : * @param[in] shift The "scale" to shift @p q by
57 : */
58 1 : #define PRIq_arg(q, precision, shift) \
59 : ((q) < 0 ? "-" : ""), (uint32_t)__PRIq_arg_get_int(q, shift), \
60 : (uint32_t)__PRIq_arg_get_frac(q, precision, shift)
61 :
62 : /**
63 : * @}
64 : */
65 :
66 : #endif /* ZEPHYR_INCLUDE_DSP_PRINT_FORMAT_H_ */
|