diff options
Diffstat (limited to 'firmware/include/bitarray.h')
-rw-r--r-- | firmware/include/bitarray.h | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/firmware/include/bitarray.h b/firmware/include/bitarray.h new file mode 100644 index 0000000000..4777ccb6a4 --- /dev/null +++ b/firmware/include/bitarray.h | |||
@@ -0,0 +1,231 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2014 by Michael Sevakis | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef BITARRAY_H | ||
22 | #define BITARRAY_H | ||
23 | |||
24 | /* Type-checked bit array definitions */ | ||
25 | |||
26 | /* All this stuff gets optimized into very simple object code */ | ||
27 | |||
28 | #define BITARRAY_WORD_BITS \ | ||
29 | (sizeof (unsigned int) * 8) | ||
30 | #define BITARRAY_NWORDS(bits) \ | ||
31 | (((bits) + BITARRAY_WORD_BITS - 1) / BITARRAY_WORD_BITS) | ||
32 | #define BITARRAY_BITWORD(bitnum) \ | ||
33 | ((bitnum) / BITARRAY_WORD_BITS) | ||
34 | #define BITARRAY_WORDBIT(bitnum) \ | ||
35 | ((bitnum) % BITARRAY_WORD_BITS) | ||
36 | #define BITARRAY_NBIT(word, bit) \ | ||
37 | ((word)*BITARRAY_WORD_BITS + (bit)) | ||
38 | #define BITARRAY_BITS(bits) \ | ||
39 | (BITARRAY_NWORDS(bits)*BITARRAY_WORD_BITS) | ||
40 | #define BITARRAY_BITN(bitnum) \ | ||
41 | (1u << BITARRAY_WORDBIT(bitnum)) | ||
42 | |||
43 | |||
44 | /** Iterators **/ | ||
45 | #include "config.h" | ||
46 | #include <stdint.h> | ||
47 | |||
48 | #if (defined(CPU_ARM) && ARM_ARCH >= 5) || UINT32_MAX < UINT_MAX | ||
49 | #define __BITARRAY_CTZ(wval) __builtin_ctz(wval) | ||
50 | #else | ||
51 | #include "system.h" | ||
52 | #define __BITARRAY_CTZ(wval) find_first_set_bit(wval) | ||
53 | #endif | ||
54 | #define __BITARRAY_POPCNT(wval) __builtin_popcount(wval) | ||
55 | |||
56 | #ifndef BIT_N | ||
57 | #define BIT_N(n) (1u << (n)) | ||
58 | #endif | ||
59 | |||
60 | /* Enumerate each word index */ | ||
61 | #define FOR_EACH_BITARRAY_WORD_INDEX(nwords, index) \ | ||
62 | for (unsigned int index = 0, _nwords = (nwords); \ | ||
63 | index < _nwords; index++) | ||
64 | |||
65 | /* Enumerate each word value */ | ||
66 | #define FOR_EACH_BITARRAY_WORD(a, wval) \ | ||
67 | FOR_EACH_BITARRAY_WORD_INDEX(ARRAYLEN((a)->words), _w) \ | ||
68 | for (unsigned int wval = (a)->words[_w], _ = 1; _; _--) | ||
69 | |||
70 | /* Enumerate the bit number of each set bit of a word in sequence */ | ||
71 | #define FOR_EACH_BITARRAY_SET_WORD_BIT(wval, bit) \ | ||
72 | for (unsigned int _wval = (wval), bit; \ | ||
73 | _wval ? (((bit) = __BITARRAY_CTZ(_wval)), 1) : 0; \ | ||
74 | _wval &= ~BIT_N(bit)) | ||
75 | |||
76 | /* Enumerate the bit number of each set bit in the bit array in sequence */ | ||
77 | #define FOR_EACH_BITARRAY_SET_BIT_ARR(nwords, words, nbit) \ | ||
78 | FOR_EACH_BITARRAY_WORD_INDEX(nwords, _w) \ | ||
79 | FOR_EACH_BITARRAY_SET_WORD_BIT(words[_w], _bit) \ | ||
80 | for (unsigned int nbit = BITARRAY_NBIT(_w, _bit), _ = 1; _; _--) | ||
81 | |||
82 | /* As above but takes an array type for an argument */ | ||
83 | #define FOR_EACH_BITARRAY_SET_BIT(a, nbit) \ | ||
84 | FOR_EACH_BITARRAY_SET_BIT_ARR(ARRAYLEN((a)->words), (a)->words, nbit) | ||
85 | |||
86 | |||
87 | /** Base functions (called by typed functions) **/ | ||
88 | |||
89 | /* Return the word associated with the bit */ | ||
90 | static inline unsigned int | ||
91 | __bitarray_get_word(unsigned int words[], unsigned int bitnum) | ||
92 | { | ||
93 | return words[BITARRAY_BITWORD(bitnum)]; | ||
94 | } | ||
95 | |||
96 | /* Set the word associated with the bit */ | ||
97 | static inline void | ||
98 | __bitarray_set_word(unsigned int words[], unsigned int bitnum, | ||
99 | unsigned int wordval) | ||
100 | { | ||
101 | words[BITARRAY_BITWORD(bitnum)] = wordval; | ||
102 | } | ||
103 | |||
104 | /* Set the bit at index 'bitnum' to '1' */ | ||
105 | static inline void | ||
106 | __bitarray_set_bit(unsigned int words[], unsigned int bitnum) | ||
107 | { | ||
108 | unsigned int word = BITARRAY_BITWORD(bitnum); | ||
109 | unsigned int bit = BITARRAY_BITN(bitnum); | ||
110 | words[word] |= bit; | ||
111 | } | ||
112 | |||
113 | /* Set the bit at index 'bitnum' to '0' */ | ||
114 | static inline void | ||
115 | __bitarray_clear_bit(unsigned int words[], unsigned int bitnum) | ||
116 | { | ||
117 | unsigned int word = BITARRAY_BITWORD(bitnum); | ||
118 | unsigned int bit = BITARRAY_BITN(bitnum); | ||
119 | words[word] &= ~bit; | ||
120 | } | ||
121 | |||
122 | /* Return the value of the specified bit ('0' or '1') */ | ||
123 | static inline unsigned int | ||
124 | __bitarray_test_bit(const unsigned int words[], unsigned int bitnum) | ||
125 | { | ||
126 | unsigned int word = BITARRAY_BITWORD(bitnum); | ||
127 | unsigned int nbit = BITARRAY_WORDBIT(bitnum); | ||
128 | return (words[word] >> nbit) & 1u; | ||
129 | } | ||
130 | |||
131 | /* Check if all bits in the bit array are '0' */ | ||
132 | static inline bool | ||
133 | __bitarray_is_clear(const unsigned int words[], unsigned int nbits) | ||
134 | { | ||
135 | FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word) | ||
136 | { | ||
137 | if (words[word] != 0) | ||
138 | return false; | ||
139 | } | ||
140 | |||
141 | return true; | ||
142 | } | ||
143 | |||
144 | /* Set every bit in the array to '0' */ | ||
145 | static inline void | ||
146 | __bitarray_clear(unsigned int words[], unsigned int nbits) | ||
147 | { | ||
148 | FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word) | ||
149 | words[word] = 0; | ||
150 | } | ||
151 | |||
152 | /* Set every bit in the array to '1' */ | ||
153 | static inline void | ||
154 | __bitarray_set(unsigned int words[], unsigned int nbits) | ||
155 | { | ||
156 | FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word) | ||
157 | words[word] = ~0u; | ||
158 | } | ||
159 | |||
160 | /* Find the lowest-indexed '1' bit in the bit array, returning the size of | ||
161 | the array if none are set */ | ||
162 | static inline unsigned int | ||
163 | __bitarray_ffs(const unsigned int words[], unsigned int nbits) | ||
164 | { | ||
165 | FOR_EACH_BITARRAY_SET_BIT_ARR(BITARRAY_NWORDS(nbits), words, nbit) | ||
166 | return nbit; | ||
167 | |||
168 | return BITARRAY_BITS(nbits); | ||
169 | } | ||
170 | |||
171 | /* Return the number of bits currently set to '1' in the bit array */ | ||
172 | static inline unsigned int | ||
173 | __bitarray_popcount(const unsigned int words[], unsigned int nbits) | ||
174 | { | ||
175 | unsigned int count = 0; | ||
176 | |||
177 | FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word) | ||
178 | count += __BITARRAY_POPCNT(words[word]); | ||
179 | |||
180 | return count; | ||
181 | } | ||
182 | |||
183 | /** | ||
184 | * Giant macro to define all the typed functions | ||
185 | * typename: The name of the type (e.g. myarr_t myarr;) | ||
186 | * fnprefix: The prefix all functions get (e.g. myarr_set_bit) | ||
187 | * nbits : The minimum number of bits the array is meant to hold | ||
188 | * (the implementation rounds this up to the word size | ||
189 | * and all words may be fully utilized) | ||
190 | * | ||
191 | * uses 'typedef' to freely change from, e.g., struct to union without | ||
192 | * changing source code | ||
193 | */ | ||
194 | #define BITARRAY_TYPE_DECLARE(typename, fnprefix, nbits) \ | ||
195 | typedef struct \ | ||
196 | { \ | ||
197 | unsigned int words[BITARRAY_NWORDS(nbits)]; \ | ||
198 | } typename; \ | ||
199 | static inline unsigned int \ | ||
200 | fnprefix##_get_word(typename *array, unsigned int bitnum) \ | ||
201 | { return __bitarray_get_word(array->words, bitnum); } \ | ||
202 | static inline void \ | ||
203 | fnprefix##_set_word(typename *array, unsigned int bitnum, \ | ||
204 | unsigned int wordval) \ | ||
205 | { __bitarray_set_word(array->words, bitnum, wordval); } \ | ||
206 | static inline void \ | ||
207 | fnprefix##_set_bit(typename *array, unsigned int bitnum) \ | ||
208 | { __bitarray_set_bit(array->words, bitnum); } \ | ||
209 | static inline void \ | ||
210 | fnprefix##_clear_bit(typename *array, unsigned int bitnum) \ | ||
211 | { __bitarray_clear_bit(array->words, bitnum); } \ | ||
212 | static inline unsigned int \ | ||
213 | fnprefix##_test_bit(const typename *array, unsigned int bitnum) \ | ||
214 | { return __bitarray_test_bit(array->words, bitnum); } \ | ||
215 | static inline bool \ | ||
216 | fnprefix##_is_clear(const typename *array) \ | ||
217 | { return __bitarray_is_clear(array->words, nbits); } \ | ||
218 | static inline void \ | ||
219 | fnprefix##_clear(typename *array) \ | ||
220 | { __bitarray_clear(array->words, nbits); } \ | ||
221 | static inline void \ | ||
222 | fnprefix##_set(typename *array) \ | ||
223 | { __bitarray_set(array->words, nbits); } \ | ||
224 | static inline unsigned int \ | ||
225 | fnprefix##_ffs(const typename *array) \ | ||
226 | { return __bitarray_ffs(array->words, nbits); } \ | ||
227 | static inline unsigned int \ | ||
228 | fnprefix##_popcount(const typename *array) \ | ||
229 | { return __bitarray_popcount(array->words, nbits); } | ||
230 | |||
231 | #endif /* BITARRAY_H */ | ||