// Example program #include #include #include /** * @brief Template class for portable Bitfields * * @tparam T type of variable in which the bitfield resides * @tparam START bit index starting from LSB where the bitfield starts * @tparam SIZE number of bits */ template struct BitField { /** * @brief Construct a new Bit Field object * */ BitField() { static_assert(SIZE != 0, "Bitfield SIZE must be > 0!"); static_assert(START < sizeof(T) * 8, "START exceeds number of bits of the chosen typename T!"); } /** * @brief assignment operator * * @param v value to be written in the bitfield * @return BitField& */ BitField& operator =(T v) { /* // this step can be optimised for systems that support bitbandalias T mask = ((1ULL << SIZE)-1) << START; _raw &= ~mask; _raw |= ((v & ((1ULL << SIZE)-1)) << START); return *this; */ //#ifdef old //TODO: test = problem with |= instead of = // mask creation for v : https://stackoverflow.com/questions/1392059/algorithm-to-generate-bit-mask _raw = ((v & ((1ULL << SIZE)-1)) << START) | (_raw & ~(((1ULL << SIZE)-1) << START)); return *this; //#endif } /** * @brief return the value inside the bitfield * * @return T */ operator T() const { return _raw >> START; } /** * @brief return the raw value * * @return T */ T operator ()() const { return _raw; } private: T _raw; }; union Reg_Control { // bit 4 struct POWER_DEV{ typedef BitField Bits; enum{TURN_OFF = 0, TURN_ON = 1}; }; // bits 2-3 struct SPEED{ typedef BitField Bits; enum{STAND_STILL = 0, SLOW = 1, NORMAL = 2, FAST = 3}; }; struct Bits{ Reg_Control::POWER_DEV::Bits POWER_DEV; Reg_Control::SPEED::Bits SPEED; } bits; // raw value. all bitfields will be "unified" here ;) uint8_t raw; // union Ctor with default value set to 0x00 Reg_Control(uint8_t v = 0x00) : raw(v) {} }; int main() { Reg_Control reg; reg.bits.SPEED = Reg_Control::SPEED::FAST; reg.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_ON; std::cout << +reg.raw << std::endl; reg.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_OFF; reg.bits.SPEED = Reg_Control::SPEED::SLOW; std::cout << +reg.raw << std::endl; return 0; }