Line data Source code
1 : /* ✔ */ 2 : 3 : #pragma once 4 : 5 : #include <Helpers/Error.hpp> 6 : #include <stdint.h> 7 : 8 : /// @addtogroup Containers 9 : /// @{ 10 : 11 : /** 12 : * @brief A class for arrays of bits. 13 : * 14 : * @tparam N 15 : * The number of bits. 16 : */ 17 : template <uint8_t N> 18 6 : class BitArray { 19 : public: 20 : /** 21 : * @brief Get the value of the given bit. 22 : * 23 : * @param bitIndex 24 : * The (zero-based) index of the bit to read. 25 : */ 26 65 : bool get(uint8_t bitIndex) { 27 65 : return buffer[getBufferIndex(bitIndex)] & getBufferMask(bitIndex); 28 : } 29 : 30 : /** 31 : * @brief Set the value of the given bit to 1. 32 : * 33 : * @param bitIndex 34 : * The (zero-based) index of the bit to set. 35 : */ 36 3 : void set(uint8_t bitIndex) { 37 3 : buffer[getBufferIndex(bitIndex)] |= getBufferMask(bitIndex); 38 3 : } 39 : 40 : /** 41 : * @brief Clear the value of the given bit to 0. 42 : * 43 : * @param bitIndex 44 : * The (zero-based) index of the bit to clear. 45 : */ 46 2 : void clear(uint8_t bitIndex) { 47 2 : buffer[getBufferIndex(bitIndex)] &= ~getBufferMask(bitIndex); 48 2 : } 49 : 50 : /** 51 : * @brief Set the value of the given bit to the given state. 52 : * 53 : * @param bitIndex 54 : * The (zero-based) index of the bit to set. 55 : * @param state 56 : * The value to set the bit to. 57 : */ 58 2 : void set(uint8_t bitIndex, bool state) { 59 2 : state ? set(bitIndex) : clear(bitIndex); 60 2 : } 61 : 62 : /** 63 : * @brief Check the given byte index, and return it if it is within the 64 : * bounds of the array, otherwise, throw an error, and return 65 : * the last valid index. 66 : * 67 : * @param byteIndex 68 : * The index to check. 69 : */ 70 70 : uint8_t safeIndex(uint8_t byteIndex) const { 71 70 : if (byteIndex >= getBufferLength()) { 72 1 : ERROR(F("Error: index out of bounds (") 73 : << byteIndex << F(", length is ") << getBufferLength() 74 : << ')', 75 : 0xFFFF); 76 0 : return getBufferLength() - 1; 77 : } 78 69 : return byteIndex; 79 70 : } 80 : 81 : /** 82 : * @brief Get the byte at the given index. 83 : * 84 : * This function can be used to quickly access all of the bits, to send 85 : * them out to a shift register, for example. 86 : * 87 : * @note No bounds checking is performed. 88 : * 89 : * @param byteIndex 90 : * The index of the byte within the array. 91 : */ 92 : uint8_t getByte(uint8_t byteIndex) const { 93 : return buffer[byteIndex]; 94 : // return buffer[safeIndex(byteIndex)]; 95 : } 96 : 97 : /** 98 : * @brief Get the buffer length in bytes. 99 : */ 100 71 : uint8_t getBufferLength() const { return bufferLength; } 101 : 102 : private: 103 70 : uint8_t getBufferIndex(uint8_t bitIndex) const { 104 70 : return safeIndex(bitIndex / 8); 105 : } 106 69 : uint8_t getBufferBit(uint8_t bitIndex) const { return bitIndex % 8; } 107 69 : uint8_t getBufferMask(uint8_t bitIndex) const { 108 69 : return 1 << getBufferBit(bitIndex); 109 : } 110 : 111 : constexpr static uint8_t bufferLength = (uint8_t)((N + 7) / 8); 112 6 : uint8_t buffer[bufferLength] = {}; 113 : }; 114 : 115 : /// @}