Position hold depends on GPS (#14101)
[betaflight.git] / src / main / common / utils.h
blob3ec18bdd06aa4d82d2a976eae6e93f71be6932d7
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 #pragma once
23 #include <stddef.h>
24 #include <stdint.h>
26 #define NOOP do {} while (0)
28 #define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
29 #define ARRAYEND(x) (&(x)[ARRAYLEN(x)])
31 #define CONST_CAST(type, value) ((type)(value))
33 #define CONCAT_HELPER(x,y) x ## y
34 #define CONCAT(x,y) CONCAT_HELPER(x, y)
35 #define CONCAT2(_1,_2) CONCAT(_1, _2)
36 #define CONCAT3(_1,_2,_3) CONCAT(CONCAT(_1, _2), _3)
37 #define CONCAT4(_1,_2,_3,_4) CONCAT(CONCAT3(_1, _2, _3), _4)
39 #define STR_HELPER(x) #x
40 #define STR(x) STR_HELPER(x)
42 #define EXPAND_I(x) x
43 #define EXPAND(x) EXPAND_I(x)
45 // expand to t if bit is 1, f when bit is 0. Other bit values are not supported
46 #define PP_IIF(bit, t, f) PP_IIF_I(bit, t, f)
47 #define PP_IIF_I(bit, t, f) PP_IIF_ ## bit(t, f)
48 #define PP_IIF_0(t, f) f
49 #define PP_IIF_1(t, f) t
51 // Expand all arguments and call macro with them. When expansion of some argument contains ',', it will be passed as multiple arguments
52 // #define TAKE3(_1,_2,_3) CONCAT3(_1,_2,_3)
53 // #define MULTI2 A,B
54 // PP_CALL(TAKE3, MULTI2, C) expands to ABC
55 #define PP_CALL(macro, ...) macro(__VA_ARGS__)
57 #if !defined(UNUSED)
58 #define UNUSED(x) (void)(x) // Variables and parameters that are not used
59 #endif
61 #define DISCARD(x) (void)(x) // To explicitly ignore result of x (usually an I/O register access).
63 #ifndef __cplusplus
64 #define STATIC_ASSERT(condition, name) _Static_assert((condition), #name)
65 #else
66 // since C++11
67 #define STATIC_ASSERT(condition, name) static_assert((condition), #name)
68 #endif
70 #define BIT(x) (1 << (x))
73 http://resnet.uoregon.edu/~gurney_j/jmpc/bitwise.html
75 #define BITCOUNT(x) (((BX_(x)+(BX_(x)>>4)) & 0x0F0F0F0F) % 255)
76 #define BX_(x) ((x) - (((x)>>1)&0x77777777) - (((x)>>2)&0x33333333) - (((x)>>3)&0x11111111))
78 static inline int popcount(unsigned x) { return __builtin_popcount(x); }
79 static inline int popcount32(uint32_t x) { return __builtin_popcount(x); }
80 static inline int popcount64(uint64_t x) { return __builtin_popcountll(x); }
83 * https://groups.google.com/forum/?hl=en#!msg/comp.lang.c/attFnqwhvGk/sGBKXvIkY3AJ
84 * Return (v ? floor(log2(v)) : 0) when 0 <= v < 1<<[8, 16, 32, 64].
85 * Inefficient algorithm, intended for compile-time constants.
87 #define LOG2_8BIT(v) (8 - 90/(((v)/4+14)|1) - 2/((v)/2+1))
88 #define LOG2_16BIT(v) (8*((v)>255) + LOG2_8BIT((v) >>8*((v)>255)))
89 #define LOG2_32BIT(v) (16*((v)>65535L) + LOG2_16BIT((v)*1L >>16*((v)>65535L)))
90 #define LOG2_64BIT(v) \
91 (32*((v)/2L>>31 > 0) \
92 + LOG2_32BIT((v)*1L >>16*((v)/2L>>31 > 0) \
93 >>16*((v)/2L>>31 > 0)))
94 #define LOG2(v) LOG2_64BIT(v)
96 #if 0
97 // ISO C version, but no type checking
98 #define container_of(ptr, type, member) \
99 ((type *) ((char *)(ptr) - offsetof(type, member)))
100 #else
101 // non ISO variant from linux kernel; checks ptr type, but triggers 'ISO C forbids braced-groups within expressions [-Wpedantic]'
102 // __extension__ is here to disable this warning
103 #define container_of(ptr, type, member) ( __extension__ ({ \
104 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
105 (type *)( (char *)__mptr - offsetof(type,member) );}))
107 static inline int16_t cmp16(uint16_t a, uint16_t b) { return (int16_t)(a-b); }
108 static inline int32_t cmp32(uint32_t a, uint32_t b) { return (int32_t)(a-b); }
110 static inline uint32_t llog2(uint32_t n) { return 31 - __builtin_clz(n | 1); }
112 // using memcpy_fn will force memcpy function call, instead of inlining it. In most cases function call takes fewer instructions
113 // than inlined version (inlining is cheaper for very small moves < 8 bytes / 2 store instructions)
114 #if defined(UNIT_TEST) || defined(SIMULATOR_BUILD)
115 // Call memcpy when building unittest - this is easier that asm symbol name mangling (symbols start with _underscore on win32)
116 #include <string.h>
117 static inline void memcpy_fn ( void * destination, const void * source, size_t num ) { memcpy(destination, source, num); }
118 #else
119 void * memcpy_fn ( void * destination, const void * source, size_t num ) asm("memcpy");
120 #endif
122 #endif
124 #if __GNUC__ > 6
125 #define FALLTHROUGH ;__attribute__ ((fallthrough))
126 #else
127 #define FALLTHROUGH do {} while(0)
128 #endif