Mozzi  version v2.0
sound synthesis library for Arduino
mozzi_macros.h
1 /*
2  * mozzi_macros.h
3  *
4  * This file is part of Mozzi.
5  *
6  * Copyright 2023-2024 Thomas Friedrichsmeier and the Mozzi Team
7  *
8  * Mozzi is licensed under the GNU Lesser General Public Licence (LGPL) Version 2.1 or later.
9  *
10 */
11 
12 /** This file contains some macros used internally inside Mozzi. These are not meant to be useful in user code. */
13 
14 #ifndef MOZZI_MACROS_H
15 #define MOZZI_MACROS_H
16 
17 
18 // internal dummy that should be distinct from any valid config value
19 #define MOZZI__INVALID_CONFIG_VALUE 9999976543210
20 
21 // internal implementation of MOZZI_CHECK_SUPPORTED
22 #define MOZZI__CHECK_SUPPORTED(X, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, ...)
23  static_assert(X != MOZZI__INVALID_CONFIG_VALUE &&
24  (X == A0 || X == A1 || X == A2 || X == A3 || X == A4 || X == A5 || X == A6 || X == A7 || X == A8 || X == A9 ||
25  X == B0 || X == B1 || X == B2 || X == B3 || X == B4 || X == B5 || X == B6 || X == B7 || X == B8 || X == B9), "Compile time option " M " does not support value " #X " on this platform.");
26 
27 // MSVC needs this indirection for proper __VA_ARGS__ expansion. I case we ever need to support MSVC...
28 #define MOZZI__MACRO_EVAL(...) __VA_ARGS__
29 
30 /** @file mozzi_internal_macros
31  * compile time check whether the given first value (usually specified as a #define) is among the values specified in subsequent args (up to 20)
32  *
33  * Example: @code MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PWM, MOZZI_OUTPUT_EXTERNAL) @endcode
34 */
35 #define MOZZI_CHECK_SUPPORTED(X, ...) MOZZI__MACRO_EVAL(MOZZI__CHECK_SUPPORTED(X, #X, __VA_ARGS__,
40 
41 /** @file mozzi_internal_macros
42  * Compile time check to complain if the given argument is not a power of two */
43 #define MOZZI_CHECK_POW2(X) static_assert((X & (X - 1)) == 0, #X " must be a power of two");
44 
45 #define MOZZI__IS(X, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, ...)
46  ((X == A0) || (X == A1) || (X == A2) || (X == A3) || (X == A4) || (X == A5) || (X == A6) || (X == A7) || (X == A8) || (X == A9) || (X == B0) || (X == B1) || (X == B2) || (X == B3) || (X == B4) || (X == B5) || (X == B6) || (X == B7) || (X == B8) || (X == B9))
47 
48 /** @file mozzi_internal_macros
49  * Short-hand to check if given first value is any of the following values (up to 20).
50  *
51  * (Orgignally, this macro was intended to also produce an error, should any of the values be non-defined (such as because it's a typo), but alas, the preprocessor would
52  * let me have that).
53  *
54  * Example: @code
55  * #if MOZZI_IS_ANY(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PWM, MOZZI_OUTPUT_2PIN_PWM, MOZZI_OUTPUT_EXTERNAL_TIMED)
56  * [...]
57  * #endif
58  * @endcode
59  *
60  * See also @ref MOZZI_CHECK_SUPPORTED, which throws an error, if the first value is not among the latter values.
61  */
62 #define MOZZI_IS(X, ...) MOZZI__MACRO_EVAL(MOZZI__IS(X, __VA_ARGS__,
67 
68 /** @file mozzi_internal_macros
69  * Short-hand for a compile time complaint, if the given define does not have the expected value.
70  *
71  * Use this to check - and clarify - complex nested logic inside #fidefs.
72  *
73  * Example: @code
74  * #if MOZZI_IS(MOZZI_ANALOG_READ, MOZZI_ANALOG_STANDARD)
75  * [long difficult to read logic, with further nested #if's]]
76  * #else
77  * MOZZI_ASSERT_EQUAL(MOZZI_ANALOG_READ, MOZZI_ANALOG_NONE)
78  * [more complex logic]
79  * #endif
80  * @endcode
81  */
82 #define MOZZI_ASSERT_EQUAL(X, Y) static_assert(X == Y, "Internal error in preprocessor logic: " #X " != " #Y ".");
83 
84 /** @file mozzi_internal_macros
85  * See MOZZI_ASSERT_EQUAL, but reversed */
86 #define MOZZI_ASSERT_NOTEQUAL(X, Y) static_assert(X != Y, "Internal error in preprocessor logic: " #X " == " #Y ".");
87 
88 
89 #if __cplusplus >= 201402L
90 /** @file mozzi_internal_macros
91  * Document that a function has been deprecated, and when, if possible giving the user an explanatory message */
92 #define MOZZI_DEPRECATED(WHEN, WHY) [[deprecated(WHY)]]
93 #elif defined(__GNUC__) && __has_cpp_attribute(deprecated)
94 #define MOZZI_DEPRECATED(WHEN, WHY) [[deprecated(WHY)]]
95 #elif defined(__GNUC__) || defined(__clang__)
96 #define MOZZI_DEPRECATED(WHEN, WHY) __attribute__((deprecated))
97 #elif defined(_MSC_VER)
98 #define MOZZI_DEPRECATED(WHEN, WHY) __declspec(deprecated)
99 #else
100 #define MOZZI_DEPRECATED(WHEN, WHY)
101 #endif
102 
103 /** @file mozzi_internal_macros
104  * Document that a function is not implemented on this platform */
105 #define MOZZI_UNIMPLEMENTED() MOZZI_DEPRECATED("n/a", "This feature is not implemented on this platform.")
106 
107 #endif