Skip to content

Commit c378761

Browse files
authored
Merge pull request #86 from elbeno/uint8_t-register
🐛 Fix writing to registers whose size is less than `sizeof(int)`
2 parents 7b47e86 + a7cfaef commit c378761

File tree

4 files changed

+60
-4
lines changed

4 files changed

+60
-4
lines changed

include/groov/config.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ struct field : named_container<Name, SubFields...> {
117117

118118
template <std::unsigned_integral RegType>
119119
constexpr static auto insert(RegType &dest, type_t value) -> void {
120-
dest = (dest & ~mask<RegType>) | (static_cast<RegType>(value) << Lsb);
120+
dest = static_cast<RegType>((dest & ~mask<RegType>) |
121+
(static_cast<RegType>(value) << Lsb));
121122
}
122123

123124
template <pathlike P> constexpr static auto resolve(P p) {

include/groov/write.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010

1111
#include <boost/mp11/algorithm.hpp>
1212

13-
template <typename...> struct undef;
14-
1513
namespace groov {
1614
namespace detail {
1715
template <typename Register, typename Spec, typename Mask, typename IdMask,

test/read.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,31 @@ TEST_CASE("read a register with integral constant address", "[read]") {
203203
auto r = sync_read(g / "reg"_r);
204204
CHECK(r["reg"_r] == data<42>);
205205
}
206+
207+
namespace {
208+
struct bus_u8 {
209+
template <auto Mask> static auto read(auto addr) -> async::sender auto {
210+
return async::just_result_of([=] { return *addr; });
211+
}
212+
213+
struct dummy_sender {
214+
using is_sender = void;
215+
};
216+
template <auto...> static auto write(auto...) -> async::sender auto {
217+
return dummy_sender{};
218+
}
219+
};
220+
221+
std::uint8_t data_u8{};
222+
using R_u8 =
223+
groov::reg<"reg", std::uint8_t, &data_u8, groov::w::replace, F0, F1, F2>;
224+
using G_u8 = groov::group<"group", bus_u8, R_u8>;
225+
constexpr auto grp_u8 = G_u8{};
226+
} // namespace
227+
228+
TEST_CASE("read a std::uint8_t register", "[read]") {
229+
using namespace groov::literals;
230+
data_u8 = 0xa5u;
231+
auto r = sync_read(grp_u8 / "reg"_r);
232+
CHECK(r["reg"_r] == data_u8);
233+
}

test/write.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ struct ct_address_bus {
146146
};
147147
} // namespace
148148

149-
TEST_CASE("write a register with integral constant address", "[read]") {
149+
TEST_CASE("write a register with integral constant address", "[write]") {
150150
using R =
151151
groov::reg<"reg", std::uint32_t, std::integral_constant<int, 42>{}>;
152152
constexpr auto g = groov::group<"group", ct_address_bus, R>{};
@@ -155,3 +155,32 @@ TEST_CASE("write a register with integral constant address", "[read]") {
155155
sync_write(g("reg"_r = 0xa5a5'a5a5u));
156156
CHECK(data<42> == 0xa5a5'a5a5u);
157157
}
158+
159+
namespace {
160+
struct bus_u8 {
161+
struct dummy_sender {
162+
using is_sender = void;
163+
};
164+
template <auto> static auto read(auto) -> async::sender auto {
165+
return dummy_sender{};
166+
}
167+
168+
template <auto Mask, auto IdMask, auto IdValue>
169+
static auto write(auto addr, auto value) -> async::sender auto {
170+
return async::just_result_of([=] { *addr = (*addr & ~Mask) | value; });
171+
}
172+
};
173+
174+
std::uint8_t data_u8{};
175+
using R_u8 =
176+
groov::reg<"reg", std::uint8_t, &data_u8, groov::w::replace, F0, F1, F2>;
177+
using G_u8 = groov::group<"group", bus_u8, R_u8>;
178+
constexpr auto grp_u8 = G_u8{};
179+
} // namespace
180+
181+
TEST_CASE("write a std::uint8_t register", "[write]") {
182+
using namespace groov::literals;
183+
data_u8 = 0b1'1010'1u;
184+
sync_write(grp_u8("reg.field1"_f = 1));
185+
CHECK(data_u8 == 0b1'0001'1u);
186+
}

0 commit comments

Comments
 (0)