summaryrefslogtreecommitdiffstats
path: root/firmware/include/bitarray.h
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/include/bitarray.h')
-rw-r--r--firmware/include/bitarray.h231
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 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2014 by Michael Sevakis
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef BITARRAY_H
+#define BITARRAY_H
+
+/* Type-checked bit array definitions */
+
+/* All this stuff gets optimized into very simple object code */
+
+#define BITARRAY_WORD_BITS \
+ (sizeof (unsigned int) * 8)
+#define BITARRAY_NWORDS(bits) \
+ (((bits) + BITARRAY_WORD_BITS - 1) / BITARRAY_WORD_BITS)
+#define BITARRAY_BITWORD(bitnum) \
+ ((bitnum) / BITARRAY_WORD_BITS)
+#define BITARRAY_WORDBIT(bitnum) \
+ ((bitnum) % BITARRAY_WORD_BITS)
+#define BITARRAY_NBIT(word, bit) \
+ ((word)*BITARRAY_WORD_BITS + (bit))
+#define BITARRAY_BITS(bits) \
+ (BITARRAY_NWORDS(bits)*BITARRAY_WORD_BITS)
+#define BITARRAY_BITN(bitnum) \
+ (1u << BITARRAY_WORDBIT(bitnum))
+
+
+/** Iterators **/
+#include "config.h"
+#include <stdint.h>
+
+#if (defined(CPU_ARM) && ARM_ARCH >= 5) || UINT32_MAX < UINT_MAX
+#define __BITARRAY_CTZ(wval) __builtin_ctz(wval)
+#else
+#include "system.h"
+#define __BITARRAY_CTZ(wval) find_first_set_bit(wval)
+#endif
+#define __BITARRAY_POPCNT(wval) __builtin_popcount(wval)
+
+#ifndef BIT_N
+#define BIT_N(n) (1u << (n))
+#endif
+
+/* Enumerate each word index */
+#define FOR_EACH_BITARRAY_WORD_INDEX(nwords, index) \
+ for (unsigned int index = 0, _nwords = (nwords); \
+ index < _nwords; index++)
+
+/* Enumerate each word value */
+#define FOR_EACH_BITARRAY_WORD(a, wval) \
+ FOR_EACH_BITARRAY_WORD_INDEX(ARRAYLEN((a)->words), _w) \
+ for (unsigned int wval = (a)->words[_w], _ = 1; _; _--)
+
+/* Enumerate the bit number of each set bit of a word in sequence */
+#define FOR_EACH_BITARRAY_SET_WORD_BIT(wval, bit) \
+ for (unsigned int _wval = (wval), bit; \
+ _wval ? (((bit) = __BITARRAY_CTZ(_wval)), 1) : 0; \
+ _wval &= ~BIT_N(bit))
+
+/* Enumerate the bit number of each set bit in the bit array in sequence */
+#define FOR_EACH_BITARRAY_SET_BIT_ARR(nwords, words, nbit) \
+ FOR_EACH_BITARRAY_WORD_INDEX(nwords, _w) \
+ FOR_EACH_BITARRAY_SET_WORD_BIT(words[_w], _bit) \
+ for (unsigned int nbit = BITARRAY_NBIT(_w, _bit), _ = 1; _; _--)
+
+/* As above but takes an array type for an argument */
+#define FOR_EACH_BITARRAY_SET_BIT(a, nbit) \
+ FOR_EACH_BITARRAY_SET_BIT_ARR(ARRAYLEN((a)->words), (a)->words, nbit)
+
+
+/** Base functions (called by typed functions) **/
+
+/* Return the word associated with the bit */
+static inline unsigned int
+__bitarray_get_word(unsigned int words[], unsigned int bitnum)
+{
+ return words[BITARRAY_BITWORD(bitnum)];
+}
+
+/* Set the word associated with the bit */
+static inline void
+__bitarray_set_word(unsigned int words[], unsigned int bitnum,
+ unsigned int wordval)
+{
+ words[BITARRAY_BITWORD(bitnum)] = wordval;
+}
+
+/* Set the bit at index 'bitnum' to '1' */
+static inline void
+__bitarray_set_bit(unsigned int words[], unsigned int bitnum)
+{
+ unsigned int word = BITARRAY_BITWORD(bitnum);
+ unsigned int bit = BITARRAY_BITN(bitnum);
+ words[word] |= bit;
+}
+
+/* Set the bit at index 'bitnum' to '0' */
+static inline void
+__bitarray_clear_bit(unsigned int words[], unsigned int bitnum)
+{
+ unsigned int word = BITARRAY_BITWORD(bitnum);
+ unsigned int bit = BITARRAY_BITN(bitnum);
+ words[word] &= ~bit;
+}
+
+/* Return the value of the specified bit ('0' or '1') */
+static inline unsigned int
+__bitarray_test_bit(const unsigned int words[], unsigned int bitnum)
+{
+ unsigned int word = BITARRAY_BITWORD(bitnum);
+ unsigned int nbit = BITARRAY_WORDBIT(bitnum);
+ return (words[word] >> nbit) & 1u;
+}
+
+/* Check if all bits in the bit array are '0' */
+static inline bool
+__bitarray_is_clear(const unsigned int words[], unsigned int nbits)
+{
+ FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word)
+ {
+ if (words[word] != 0)
+ return false;
+ }
+
+ return true;
+}
+
+/* Set every bit in the array to '0' */
+static inline void
+__bitarray_clear(unsigned int words[], unsigned int nbits)
+{
+ FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word)
+ words[word] = 0;
+}
+
+/* Set every bit in the array to '1' */
+static inline void
+__bitarray_set(unsigned int words[], unsigned int nbits)
+{
+ FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word)
+ words[word] = ~0u;
+}
+
+/* Find the lowest-indexed '1' bit in the bit array, returning the size of
+ the array if none are set */
+static inline unsigned int
+__bitarray_ffs(const unsigned int words[], unsigned int nbits)
+{
+ FOR_EACH_BITARRAY_SET_BIT_ARR(BITARRAY_NWORDS(nbits), words, nbit)
+ return nbit;
+
+ return BITARRAY_BITS(nbits);
+}
+
+/* Return the number of bits currently set to '1' in the bit array */
+static inline unsigned int
+__bitarray_popcount(const unsigned int words[], unsigned int nbits)
+{
+ unsigned int count = 0;
+
+ FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word)
+ count += __BITARRAY_POPCNT(words[word]);
+
+ return count;
+}
+
+/**
+ * Giant macro to define all the typed functions
+ * typename: The name of the type (e.g. myarr_t myarr;)
+ * fnprefix: The prefix all functions get (e.g. myarr_set_bit)
+ * nbits : The minimum number of bits the array is meant to hold
+ * (the implementation rounds this up to the word size
+ * and all words may be fully utilized)
+ *
+ * uses 'typedef' to freely change from, e.g., struct to union without
+ * changing source code
+ */
+#define BITARRAY_TYPE_DECLARE(typename, fnprefix, nbits) \
+typedef struct \
+{ \
+ unsigned int words[BITARRAY_NWORDS(nbits)]; \
+} typename; \
+static inline unsigned int \
+fnprefix##_get_word(typename *array, unsigned int bitnum) \
+ { return __bitarray_get_word(array->words, bitnum); } \
+static inline void \
+fnprefix##_set_word(typename *array, unsigned int bitnum, \
+ unsigned int wordval) \
+ { __bitarray_set_word(array->words, bitnum, wordval); } \
+static inline void \
+fnprefix##_set_bit(typename *array, unsigned int bitnum) \
+ { __bitarray_set_bit(array->words, bitnum); } \
+static inline void \
+fnprefix##_clear_bit(typename *array, unsigned int bitnum) \
+ { __bitarray_clear_bit(array->words, bitnum); } \
+static inline unsigned int \
+fnprefix##_test_bit(const typename *array, unsigned int bitnum) \
+ { return __bitarray_test_bit(array->words, bitnum); } \
+static inline bool \
+fnprefix##_is_clear(const typename *array) \
+ { return __bitarray_is_clear(array->words, nbits); } \
+static inline void \
+fnprefix##_clear(typename *array) \
+ { __bitarray_clear(array->words, nbits); } \
+static inline void \
+fnprefix##_set(typename *array) \
+ { __bitarray_set(array->words, nbits); } \
+static inline unsigned int \
+fnprefix##_ffs(const typename *array) \
+ { return __bitarray_ffs(array->words, nbits); } \
+static inline unsigned int \
+fnprefix##_popcount(const typename *array) \
+ { return __bitarray_popcount(array->words, nbits); }
+
+#endif /* BITARRAY_H */