From 7726c14bee162b9148a27bb57d2df284260022c2 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Sat, 21 Dec 2024 14:06:57 -0800 Subject: [PATCH] :sparkles: Add >>/<< shifts to bit masks (#50) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ✅ Add & fix bit_value tests. - ✅ Add unit tests for the bit mask library. --- CMakeLists.txt | 1 + include/libhal-util/bit.hpp | 57 +++- tests/bit.functions.test.cpp | 537 +++++++++++++++++++---------------- 3 files changed, 347 insertions(+), 248 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 20e80fe..c648436 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ set(TEST_SOURCES_LIST tests/atomic_spin_lock.test.cpp tests/can.test.cpp tests/bit.test.cpp + tests/bit.functions.test.cpp tests/enum.test.cpp tests/i2c.test.cpp tests/input_pin.test.cpp diff --git a/include/libhal-util/bit.hpp b/include/libhal-util/bit.hpp index 37dada3..79ee96d 100644 --- a/include/libhal-util/bit.hpp +++ b/include/libhal-util/bit.hpp @@ -22,6 +22,9 @@ #include #include +// NOTE: DO not include libhal/units.hpp here. We want this file to stay as a +// dropp in header only library that just uses C++'s stdlib. + /** * @defgroup Bit Bit Operations * @@ -173,13 +176,52 @@ struct bit_mask * @ingroup Bit * @brief Comparison operator between this mask and another * - * @param other - the other mask to compare against + * @param p_other - the other mask to compare against * @return true - the masks are the same * @return false - the masks are not the same */ - constexpr bool operator==(bit_mask const& other) + constexpr bool operator==(bit_mask const& p_other) + { + return p_other.position == position && p_other.width == width; + } + + /** + * @ingroup Bit + * @brief Shift the position of the bit mask to the right + * + * NOTE: the position will overflow if the position + * + * @param p_shift_amount - the number of bits to shift the position by + * @return constexpr auto - a copy of this bit_mask but with the position + * shifted. + */ + constexpr auto operator>>(std::uint32_t p_shift_amount) const + { + hal::bit_mask result = *this; + if (result.position > p_shift_amount) { + result.position -= p_shift_amount; + } else { + result.position = 0; + } + return result; + } + + /** + * @ingroup Bit + * @brief Shift the position of the bit mask to the left + * + * NOTE: the position will not underflow if the shift amount is greater than + * the position. The position value will saturate at the value of 0. + * + * @param p_shift_amount - the number of bits to shift the position by + * @return constexpr auto - a copy of this bit_mask but with the position + * shifted. + */ + constexpr auto operator<<(std::uint32_t p_shift_amount) const { - return other.position == position && other.width == width; + hal::bit_mask result = *this; + result.position += p_shift_amount; + return result; } }; @@ -389,6 +431,15 @@ class bit_value : m_value(p_initial_value) { } + /** + * @brief Constructs a new bit_value instance with an initial value. + * + * @param p_initial_value The initial value to use. Defaults to 0. + */ + constexpr bit_value& operator=(T p_initial_value) + { + m_value = p_initial_value; + } /** * @brief Sets (sets to a 1) multiple bits in the represented value. diff --git a/tests/bit.functions.test.cpp b/tests/bit.functions.test.cpp index 2901a8e..327d43a 100644 --- a/tests/bit.functions.test.cpp +++ b/tests/bit.functions.test.cpp @@ -18,408 +18,455 @@ namespace hal { -void bit_clear_test() -{ +boost::ut::suite<"bit_clear_test"> bit_clear_test = [] { using namespace boost::ut; "hal::bit clear() increment (0)"_test = []() { - std::uint32_t volatile control_register = 0x0; - constexpr auto clear_mask = bit::mask::from<0>(); - expect(that % 0x0000'0000 == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<1>(); - expect(that % 0x0000'0000 == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<2>(); - expect(that % 0x0000'0000 == control_register.clear()); + hal::bit_value control_register = 0x0; + expect(that % 0x0000'0000 == + control_register.clear().to()); + expect(that % 0x0000'0000 == + control_register.clear().to()); + expect(that % 0x0000'0000 == + control_register.clear().to()); }; "hal::bit clear() increment (1)"_test = []() { - std::uint32_t volatile control_register = 0x1; - constexpr auto clear_mask = bit::mask::from<0>(); - expect(that % 0x0000'0000 == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<1>(); - expect(that % 0x0000'0000 == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<2>(); - expect(that % 0x0000'0000 == control_register.clear()); + hal::bit_value control_register = 0x1; + expect(that % 0x0000'0000 == + control_register.clear().to()); + expect(that % 0x0000'0000 == + control_register.clear().to()); + expect(that % 0x0000'0000 == + control_register.clear().to()); }; "hal::bit clear() increment (2)"_test = []() { - std::uint32_t volatile control_register = 0x2; - constexpr auto clear_mask = bit::mask::from<0>(); - expect(that % 0x0000'0002 == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<1>(); - expect(that % 0x0000'0000 == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<2>(); - expect(that % 0x0000'0000 == control_register.clear()); + hal::bit_value control_register = 0x2; + expect(that % 0x0000'0002 == + control_register.clear().to()); + expect(that % 0x0000'0000 == + control_register.clear().to()); + expect(that % 0x0000'0000 == + control_register.clear().to()); }; "hal::bit clear() increment (10)"_test = []() { - std::uint32_t volatile control_register = 0xA; - constexpr auto clear_mask = bit::mask::from<0>(); - expect(that % 0x0000'000A == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<0>(); - expect(that % 0x0000'0008 == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<0>(); - expect(that % 0x0000'0008 == control_register.clear()); + hal::bit_value control_register = 0xA; + expect(that % 0x0000'000A == + control_register.clear().to()); + expect(that % 0x0000'0008 == + control_register.clear().to()); + expect(that % 0x0000'0008 == + control_register.clear().to()); }; "hal::bit clear() increment upper half (0x1'FFFF)"_test = []() { - std::uint32_t volatile control_register = 0x1'FFFF; - constexpr auto clear_mask = bit::mask::from<16>(); - expect(that % 0x0000'FFFF == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<17>(); - expect(that % 0x0000'FFFF == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<18>(); - expect(that % 0x0000'FFFF == control_register.clear()); + hal::bit_value control_register = 0x1'FFFF; + expect(that % 0x0000'FFFF == + control_register.clear().to()); + expect(that % 0x0000'FFFF == + control_register.clear().to()); + expect(that % 0x0000'FFFF == + control_register.clear().to()); }; "hal::bit clear() increment lower half (0xFFFF'FFFF)"_test = []() { - std::uint32_t volatile control_register = 0xFFFF'FFFF; - constexpr auto clear_mask = bit::mask::from<0>(); - expect(that % 0xFFFF'FFFE == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<1>(); - expect(that % 0xFFFF'FFFC == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<2>(); - expect(that % 0xFFFF'FFF8 == control_register.clear()); + hal::bit_value control_register = 0xFFFF'FFFF; + expect(that % 0xFFFF'FFFE == + control_register.clear().to()); + expect(that % 0xFFFF'FFFC == + control_register.clear().to()); + expect(that % 0xFFFF'FFF8 == + control_register.clear().to()); }; "hal::bit clear() increment upper half (0xFFFF'FFFF)"_test = []() { - std::uint32_t volatile control_register = 0xFFFF'FFFF; - constexpr auto clear_mask = bit::mask::from<16>(); - expect(that % 0xFFFE'FFFF == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<17>(); - expect(that % 0xFFFC'FFFF == control_register.clear()); - constexpr auto clear_mask = bit::mask::from<18>(); - expect(that % 0xFFF8'FFFF == control_register.clear()); + hal::bit_value control_register = 0xFFFF'FFFF; + expect(that % 0xFFFE'FFFF == + control_register.clear().to()); + expect(that % 0xFFFC'FFFF == + control_register.clear().to()); + expect(that % 0xFFF8'FFFF == + control_register.clear().to()); + }; + + "hal::bit clear() multiple bits (0xFFFF'FFFF)"_test = []() { + hal::bit_value control_register = 0xFFFF'FFFF; + expect(that % 0xFFFF'FF00 == + control_register.clear().to()); + expect( + that % 0xFFE1'FF00 == + control_register.clear().to()); + expect( + that % 0xE001'FF00 == + control_register.clear().to()); }; }; - -void bit_extract_test() -{ +boost::ut::suite<"bit_extract_test"> bit_extract_test = [] { using namespace boost::ut; "hal::bit extract() single input increment(0)"_test = []() { - std::uint32_t volatile control_register = 0x0123'ABCD; - constexpr auto extract_mask = bit::mask::from<0>(); - auto extracted = bit::extract(control_register); + std::uint32_t control_register = 0x0123'ABCD; + constexpr auto extract_mask = bit_mask::from(0); + auto const extracted = bit_extract(control_register); expect(that % 0x1 == extracted); }; "hal::bit extract() single input increment(4)"_test = []() { - std::uint32_t volatile control_register = 0x0123'ABCD; - constexpr auto extract_mask = bit::mask::from<4>(); - auto extracted = bit::extract(control_register); + std::uint32_t control_register = 0x0123'ABCD; + constexpr auto extract_mask = bit_mask::from(4); + auto const extracted = bit_extract(control_register); expect(that % 0x0 == extracted); }; "hal::bit extract() single input increment(8)"_test = []() { - std::uint32_t volatile control_register = 0x0123'ABCD; - constexpr auto extract_mask = bit::mask::from<8>(); - auto extracted = bit::extract(control_register); + std::uint32_t control_register = 0x0123'ABCD; + constexpr auto extract_mask = bit_mask::from(8); + auto const extracted = bit_extract(control_register); expect(that % 0x1 == extracted); }; "hal::bit extract() double input increment(0)"_test = []() { - std::uint32_t volatile control_register = 0x0123'ABCD; - constexpr auto extract_mask = bit::mask::from<0, 1>(); - auto extracted = bit::extract(control_register); + std::uint32_t control_register = 0x0123'ABCD; + constexpr auto extract_mask = bit_mask::from(0, 1); + auto const extracted = bit_extract(control_register); expect(that % 0x1 == extracted); }; "hal::bit extract() double input increment(4)"_test = []() { - std::uint32_t volatile control_register = 0x0123'ABCD; - constexpr auto extract_mask = bit::mask::from<0, 3>(); - auto extracted = bit::extract(control_register); + std::uint32_t control_register = 0x0123'ABCD; + constexpr auto extract_mask = bit_mask::from(0, 3); + auto const extracted = bit_extract(control_register); expect(that % 0xD == extracted); }; "hal::bit extract() double input increment(8)"_test = []() { - std::uint32_t volatile control_register = 0x0123'ABCD; - constexpr auto extract_mask = bit::mask::from<0, 7>(); - auto extracted = bit::extract(control_register); + std::uint32_t control_register = 0x0123'ABCD; + constexpr auto extract_mask = bit_mask::from(0, 7); + auto const extracted = bit_extract(control_register); expect(that % 0xCD == extracted); }; "hal::bit extract() double input increment(4,7)"_test = []() { - std::uint32_t volatile control_register = 0x0123'ABCD; - constexpr auto extract_mask = bit::mask::from<4, 7>(); - auto extracted = bit::extract(control_register); + std::uint32_t control_register = 0x0123'ABCD; + constexpr auto extract_mask = bit_mask::from(4, 7); + auto const extracted = bit_extract(control_register); expect(that % 0xC == extracted); }; "hal::bit extract() double input increment(8,15)"_test = []() { - std::uint32_t volatile control_register = 0x0123'ABCD; - constexpr auto extract_mask = bit::mask::from<8, 15>(); - auto extracted = bit::extract(control_register); + std::uint32_t control_register = 0x0123'ABCD; + constexpr auto extract_mask = bit_mask::from(8, 15); + auto const extracted = bit_extract(control_register); expect(that % 0xAB == extracted); }; "hal::bit extract() double input upper half"_test = []() { - std::uint32_t volatile control_register = 0x0123'ABCD; - constexpr auto extract_mask = bit::mask::from<16, 23>(); - auto extracted = bit::extract(control_register); + std::uint32_t control_register = 0x0123'ABCD; + constexpr auto extract_mask = bit_mask::from(16, 23); + auto const extracted = bit_extract(control_register); expect(that % 0x23 == extracted); }; "hal::bit extract() double input out of range"_test = []() { - std::uint32_t volatile control_register = 0x0123'ABCD; - constexpr auto extract_mask = bit::mask::from<24, 39>(); - auto extracted = bit::extract(control_register); + std::uint32_t control_register = 0x0123'ABCD; + constexpr auto extract_mask = bit_mask::from(24, 39); + auto const extracted = bit_extract(control_register); expect(that % 0x0001 == extracted); }; }; -void bit_insert_test() -{ +boost::ut::suite<"bit_insert_test"> bit_insert_test = [] { using namespace boost::ut; "hal::bit insert single input increment (0)"_test = []() { - std::uint32_t volatile control_register = 0x0; - static constexpr auto insert_mask = bit::mask::from<0>(); + hal::bit_value control_register = 0x0; + static constexpr auto insert_mask = bit_mask::from(0); expect(that % 0x0000'0001 == - control_register.insert(0xFFFFUL)); + control_register.insert(0xFFFFUL).to()); }; "hal::bit insert single input increment (1)"_test = []() { - std::uint32_t volatile control_register = 0x0; - static constexpr auto insert_mask = bit::mask::from<1>(); + hal::bit_value control_register = 0x0; + static constexpr auto insert_mask = bit_mask::from(1); expect(that % 0x0000'0002 == - control_register.insert(0xFFFFUL)); + control_register.insert(0xFFFFUL).to()); }; "hal::bit insert single input increment (16)"_test = []() { - std::uint32_t volatile control_register = 0x0; - static constexpr auto insert_mask = bit::mask::from<16>(); + hal::bit_value control_register = 0x0; + static constexpr auto insert_mask = bit_mask::from(16); expect(that % 0x0001'0000 == - control_register.insert(0xFFFFUL)); + control_register.insert(0xFFFFUL).to()); }; "hal::bit insert double input increment (0)"_test = []() { - std::uint32_t volatile control_register = 0xFFFF'FFFF; - static constexpr auto insert_mask = bit::mask::from<0, 15>(); + hal::bit_value control_register = 0xFFFF'FFFF; + static constexpr auto insert_mask = bit_mask::from(0, 15); expect(that % 0xFFFF'ABCD == - control_register.insert(0xABCDUL)); + control_register.insert(0xABCDUL).to()); }; "hal::bit insert double input increment (1)"_test = []() { - std::uint32_t volatile control_register = 0xFFFF'FFFF; - static constexpr auto insert_mask = bit::mask::from<1, 15>(); + hal::bit_value control_register = 0xFFFF'FFFF; + static constexpr auto insert_mask = bit_mask::from(1, 15); expect(that % 0xFFFF'579B == - control_register.insert(0xABCDUL)); + control_register.insert(0xABCDUL).to()); }; "hal::bit insert double input increment (16)"_test = []() { - std::uint32_t volatile control_register = 0xFFFF'FFFF; - static constexpr auto insert_mask = bit::mask::from<16, 31>(); + hal::bit_value control_register = 0xFFFF'FFFF; + static constexpr auto insert_mask = bit_mask::from(16, 31); expect(that % 0xABCD'FFFF == - control_register.insert(0xABCDUL)); + control_register.insert(0xABCDUL).to()); }; "hal::bit insert double input increment out of range"_test = []() { - std::uint32_t volatile control_register = 0xFFFF'FFFF; - static constexpr auto insert_mask = bit::mask::from<27, 42>(); + hal::bit_value control_register = 0xFFFF'FFFF; + static constexpr auto insert_mask = bit_mask::from(27, 42); expect(that % 0x6FFF'FFFF == - control_register.insert(0xABCDUL)); + control_register.insert(0xABCDUL).to()); }; }; -void bit_set_test() -{ +boost::ut::suite<"bit_set_test"> bit_set_test = [] { using namespace boost::ut; "hal::bit set() increment (0)"_test = []() { - std::uint32_t volatile control_register = 0x0; - constexpr auto set_mask = bit::mask::from<0>(); - expect(that % 0x0000'0001 == control_register.set()); - constexpr auto set_mask = bit::mask::from<1>(); - expect(that % 0x0000'0003 == control_register.set()); - constexpr auto set_mask = bit::mask::from<2>(); - expect(that % 0x0000'0007 == control_register.set()); + hal::bit_value control_register = 0x0; + expect(that % 0x0000'0001 == + control_register.set().to()); + expect(that % 0x0000'0003 == + control_register.set().to()); + expect(that % 0x0000'0007 == + control_register.set().to()); }; "hal::bit set() increment (1)"_test = []() { - std::uint32_t volatile control_register = 0x1; - constexpr auto set_mask = bit::mask::from<0>(); - expect(that % 0x0000'0001 == control_register.set()); - constexpr auto set_mask = bit::mask::from<1>(); - expect(that % 0x0000'0003 == control_register.set()); - constexpr auto set_mask = bit::mask::from<2>(); - expect(that % 0x0000'0007 == control_register.set()); + hal::bit_value control_register = 0x1; + expect(that % 0x0000'0001 == + control_register.set().to()); + expect(that % 0x0000'0003 == + control_register.set().to()); + expect(that % 0x0000'0007 == + control_register.set().to()); }; "hal::bit set() increment (2)"_test = []() { - std::uint32_t volatile control_register = 0x2; - constexpr auto set_mask = bit::mask::from<0>(); - expect(that % 0x0000'0003 == control_register.set()); - constexpr auto set_mask = bit::mask::from<1>(); - expect(that % 0x0000'0003 == control_register.set()); - constexpr auto set_mask = bit::mask::from<2>(); - expect(that % 0x0000'0007 == control_register.set()); + hal::bit_value control_register = 0x2; + expect(that % 0x0000'0003 == + control_register.set().to()); + expect(that % 0x0000'0003 == + control_register.set().to()); + expect(that % 0x0000'0007 == + control_register.set().to()); }; "hal::bit set() increment (10)"_test = []() { - std::uint32_t volatile control_register = 0xA; - constexpr auto set_mask = bit::mask::from<0>(); - expect(that % 0x0000'000B == control_register.set()); - constexpr auto set_mask = bit::mask::from<1>(); - expect(that % 0x0000'000B == control_register.set()); - constexpr auto set_mask = bit::mask::from<2>(); - expect(that % 0x0000'000F == control_register.set()); + hal::bit_value control_register = 0xA; + expect(that % 0x0000'000B == + control_register.set().to()); + expect(that % 0x0000'000B == + control_register.set().to()); + expect(that % 0x0000'000F == + control_register.set().to()); }; "hal::bit set() increment upper half (0x1'FFFF)"_test = []() { - xstd::bitset test_set(0x1'FFFF); - std::uint32_t volatile control_register = 0x1'FFFF; - constexpr auto set_mask = bit::mask::from<16>(); - expect(that % 0x0001'FFFF == control_register.set()); - constexpr auto set_mask = bit::mask::from<17>(); - expect(that % 0x0003'FFFF == control_register.set()); - constexpr auto set_mask = bit::mask::from<18>(); - expect(that % 0x0007'FFFF == control_register.set()); + hal::bit_value control_register = 0x1'FFFF; + expect(that % 0x0001'FFFF == + control_register.set().to()); + expect(that % 0x0003'FFFF == + control_register.set().to()); + expect(that % 0x0007'FFFF == + control_register.set().to()); }; }; -void bit_toggle_test() -{ +boost::ut::suite<"bit_toggle_test"> bit_toggle_test = [] { using namespace boost::ut; "hal::bit toggle() increment (0)"_test = []() { - std::uint32_t volatile control_register = 0x0; - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'0001 == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<1>(); - expect(that % 0x0000'0003 == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<2>(); - expect(that % 0x0000'0007 == control_register.toggle()); + hal::bit_value control_register = 0x0; + expect(that % 0x0000'0001 == + control_register.toggle().to()); + expect(that % 0x0000'0003 == + control_register.toggle().to()); + expect(that % 0x0000'0007 == + control_register.toggle().to()); }; "hal::bit toggle() alternate (0)"_test = []() { - std::uint32_t volatile control_register = 0x0; - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'0001 == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'0000 == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'0001 == control_register.toggle()); + hal::bit_value control_register = 0x0; + expect(that % 0x0000'0001 == + control_register.toggle().to()); + expect(that % 0x0000'0000 == + control_register.toggle().to()); + expect(that % 0x0000'0001 == + control_register.toggle().to()); }; "hal::bit toggle() increment (1)"_test = []() { - std::uint32_t volatile control_register = 0x1; - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'0000 == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<1>(); - expect(that % 0x0000'0002 == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<2>(); - expect(that % 0x0000'0006 == control_register.toggle()); + hal::bit_value control_register = 0x1; + expect(that % 0x0000'0000 == + control_register.toggle().to()); + expect(that % 0x0000'0002 == + control_register.toggle().to()); + expect(that % 0x0000'0006 == + control_register.toggle().to()); }; "hal::bit toggle() alternate (1)"_test = []() { - std::uint32_t volatile control_register = 0x1; - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'0000 == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'0001 == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'0000 == control_register.toggle()); + hal::bit_value control_register = 0x1; + expect(that % 0x0000'0000 == + control_register.toggle().to()); + expect(that % 0x0000'0001 == + control_register.toggle().to()); + expect(that % 0x0000'0000 == + control_register.toggle().to()); }; "hal::bit toggle() increment (2)"_test = []() { - std::uint32_t volatile control_register = 0x2; - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'0003 == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<1>(); - expect(that % 0x0000'0001 == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<2>(); - expect(that % 0x0000'0005 == control_register.toggle()); + hal::bit_value control_register = 0x2; + expect(that % 0x0000'0003 == + control_register.toggle().to()); + expect(that % 0x0000'0001 == + control_register.toggle().to()); + expect(that % 0x0000'0005 == + control_register.toggle().to()); }; "hal::bit toggle() alternate (2)"_test = []() { - std::uint32_t volatile control_register = 0x2; - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'0003 == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'0002 == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'0003 == control_register.toggle()); + hal::bit_value control_register = 0x2; + expect(that % 0x0000'0003 == + control_register.toggle().to()); + expect(that % 0x0000'0002 == + control_register.toggle().to()); + expect(that % 0x0000'0003 == + control_register.toggle().to()); }; "hal::bit toggle() increment (10)"_test = []() { - std::uint32_t volatile control_register = 0xA; - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'000B == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<1>(); - expect(that % 0x0000'0009 == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<2>(); - expect(that % 0x0000'000D == control_register.toggle()); + hal::bit_value control_register = 0xA; + expect(that % 0x0000'000B == + control_register.toggle().to()); + expect(that % 0x0000'0009 == + control_register.toggle().to()); + expect(that % 0x0000'000D == + control_register.toggle().to()); }; "hal::bit toggle() alternate (10)"_test = []() { - std::uint32_t volatile control_register = 0xA; - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'000B == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'000A == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0x0000'000B == control_register.toggle()); + hal::bit_value control_register = 0xA; + expect(that % 0x0000'000B == + control_register.toggle().to()); + expect(that % 0x0000'000A == + control_register.toggle().to()); + expect(that % 0x0000'000B == + control_register.toggle().to()); }; "hal::bit toggle() increment upper half (0x1'FFFF)"_test = []() { - std::uint32_t volatile control_register = 0x1'FFFF; - constexpr auto toggle_mask = bit::mask::from<16>(); - expect(that % 0x0000'FFFF == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<17>(); - expect(that % 0x0002'FFFF == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<18>(); - expect(that % 0x0006'FFFF == control_register.toggle()); + hal::bit_value control_register = 0x1'FFFF; + expect(that % 0x0000'FFFF == + control_register.toggle().to()); + expect(that % 0x0002'FFFF == + control_register.toggle().to()); + expect(that % 0x0006'FFFF == + control_register.toggle().to()); }; "hal::bit toggle() alternate upper half (0x1'FFFF)"_test = []() { - std::uint32_t volatile control_register = 0x1'FFFF; - constexpr auto toggle_mask = bit::mask::from<16>(); - expect(that % 0x0000'FFFF == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<16>(); - expect(that % 0x0001'FFFF == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<16>(); - expect(that % 0x0000'FFFF == control_register.toggle()); + hal::bit_value control_register = 0x1'FFFF; + expect(that % 0x0000'FFFF == + control_register.toggle().to()); + expect(that % 0x0001'FFFF == + control_register.toggle().to()); + expect(that % 0x0000'FFFF == + control_register.toggle().to()); }; "hal::bit toggle() increment lower half (0xFFFF'FFFF)"_test = []() { - std::uint32_t volatile control_register = 0xFFFF'FFFF; - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0xFFFF'FFFE == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<1>(); - expect(that % 0xFFFF'FFFC == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<2>(); - expect(that % 0xFFFF'FFF8 == control_register.toggle()); + hal::bit_value control_register = 0xFFFF'FFFF; + expect(that % 0xFFFF'FFFE == + control_register.toggle().to()); + expect(that % 0xFFFF'FFFC == + control_register.toggle().to()); + expect(that % 0xFFFF'FFF8 == + control_register.toggle().to()); }; "hal::bit toggle() alternate lower half (0xFFFF'FFFF)"_test = []() { - std::uint32_t volatile control_register = 0xFFFF'FFFF; - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0xFFFF'FFFE == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0xFFFF'FFFF == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<0>(); - expect(that % 0xFFFF'FFFE == control_register.toggle()); + hal::bit_value control_register = 0xFFFF'FFFF; + expect(that % 0xFFFF'FFFE == + control_register.toggle().to()); + expect(that % 0xFFFF'FFFF == + control_register.toggle().to()); + expect(that % 0xFFFF'FFFE == + control_register.toggle().to()); }; "hal::bit toggle() increment upper half (0xFFFF'FFFF)"_test = []() { - std::uint32_t volatile control_register = 0xFFFF'FFFF; - constexpr auto toggle_mask = bit::mask::from<16>(); - expect(that % 0xFFFE'FFFF == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<17>(); - expect(that % 0xFFFC'FFFF == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<18>(); - expect(that % 0xFFF8'FFFF == control_register.toggle()); + hal::bit_value control_register = 0xFFFF'FFFF; + expect(that % 0xFFFE'FFFF == + control_register.toggle().to()); + expect(that % 0xFFFC'FFFF == + control_register.toggle().to()); + expect(that % 0xFFF8'FFFF == + control_register.toggle().to()); }; "hal::bit toggle() alternate upper half (0xFFFF'FFFF)"_test = []() { - std::uint32_t volatile control_register = 0xFFFF'FFFF; - constexpr auto toggle_mask = bit::mask::from<16>(); - expect(that % 0xFFFE'FFFF == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<16>(); - expect(that % 0xFFFF'FFFF == control_register.toggle()); - constexpr auto toggle_mask = bit::mask::from<16>(); - expect(that % 0xFFFE'FFFF == control_register.toggle()); + hal::bit_value control_register = 0xFFFF'FFFF; + expect(that % 0xFFFE'FFFF == + control_register.toggle().to()); + expect(that % 0xFFFF'FFFF == + control_register.toggle().to()); + expect(that % 0xFFFE'FFFF == + control_register.toggle().to()); + }; +}; + +boost::ut::suite<"bit_mask_shift_test"> bit_mask_shift_test = [] { + using namespace boost::ut; + + "hal::bit_mask shift right"_test = []() { + constexpr auto mask1 = hal::bit_mask::from(0, 7); + constexpr auto mask2 = mask1 << 8U; + constexpr auto mask3 = mask2 << 8U; + constexpr auto mask4 = mask3 << 8U; + + expect(that % 0 == mask1.position); + expect(that % 8 == mask1.width); + + expect(that % 8 == mask2.position); + expect(that % 8 == mask2.width); + + expect(that % 16 == mask3.position); + expect(that % 8 == mask3.width); + + expect(that % 24 == mask4.position); + expect(that % 8 == mask4.width); + }; + + "hal::bit_mask left right"_test = []() { + constexpr auto mask1 = hal::bit_mask::from(23, 26); + constexpr auto mask2 = mask1 >> 5U; + constexpr auto mask3 = mask2 >> 5U; + constexpr auto mask4 = mask3 >> 5U; + + expect(that % 23 == mask1.position); + expect(that % 4 == mask1.width); + + expect(that % (23 - 5) == mask2.position); + expect(that % 4 == mask2.width); + + expect(that % (23 - (5 * 2)) == mask3.position); + expect(that % 4 == mask3.width); + + expect(that % (23 - (5 * 3)) == mask4.position); + expect(that % 4 == mask4.width); }; }; } // namespace hal