Skip to content

Commit

Permalink
✨ Add compile time bit_value::insert
Browse files Browse the repository at this point in the history
Add bit_value::insert API that can take a bit field and value as
template arguments resulting in a completely compile time value.

Set bit_value template to default std::uint32_t for ease of use.
  • Loading branch information
kammce committed Apr 29, 2024
1 parent 83a02bd commit 096dc8c
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 3 deletions.
11 changes: 11 additions & 0 deletions .github/workflows/4.1.0.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: 🚀 4.1.0

on:
workflow_dispatch:

jobs:
deploy:
uses: libhal/ci/.github/workflows/[email protected]
with:
version: 4.1.0
secrets: inherit
18 changes: 17 additions & 1 deletion include/libhal-util/bit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ constexpr auto bit_extract(bit_mask p_field,
return static_cast<T>(masked);
}

template<std::unsigned_integral T>
template<std::unsigned_integral T = std::uint32_t>
class bit_value
{
public:
Expand Down Expand Up @@ -373,6 +373,22 @@ class bit_value
return *this;
}

template<bit_mask p_field, std::unsigned_integral auto p_value>
constexpr auto& insert()
{
// AND value with mask to remove any bits beyond the specified width.
// Shift masked value into bit position and OR with target value.
auto shifted_field = static_cast<T>(p_value) << p_field.position;
auto new_value = shifted_field & p_field.value<T>();

// Clear width's number of bits in the target value at the bit position
// specified.
m_value = m_value & ~p_field.value<T>();
m_value = m_value | static_cast<T>(new_value);

return *this;
}

template<std::integral U>
[[nodiscard]] constexpr auto to()
{
Expand Down
6 changes: 4 additions & 2 deletions tests/bit.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,23 @@ void bit_test()
constexpr auto enable_bit = bit_mask::from<1>();
constexpr auto high_power_mode = bit_mask::from<15>();
constexpr auto clock_divider = bit_mask::from<20, 23>();
constexpr auto phase_delay = bit_mask::from<24, 27>();
constexpr auto extractor_mask = bit_mask::from<16, 23>();
constexpr auto single_bit_mask = bit_mask::from<1>();

// Exercise
bit_modify(control_register)
.set<enable_bit>()
.clear<high_power_mode>()
.insert<clock_divider>(0xAU);
.insert<clock_divider>(0xAU)
.insert<phase_delay, 0x3U>();
auto extracted = bit_extract<extractor_mask>(control_register);
auto probed = bit_extract<single_bit_mask>(control_register);
auto probed_inline =
bit_extract<bit_mask{ .position = 15, .width = 1 }>(control_register);

// Verify
expect(that % 0x00A1'0002 == control_register);
expect(that % 0x03A1'0002 == control_register);
expect(that % 0xA1 == extracted);
expect(that % 1 == probed);
expect(that % 0 == probed_inline);
Expand Down

0 comments on commit 096dc8c

Please sign in to comment.