SRS-control 0.1.4
 
Loading...
Searching...
No Matches
StructDeserializer.cpp
Go to the documentation of this file.
2
3namespace srs::process
4{
5 namespace
6 {
7 using DataElementType = StructDeserializer::DataElementType;
8
9 template <typename T>
10 auto convert_to(const DataElementType& raw_data) -> T
11 {
12 constexpr auto struct_size = sizeof(uint64_t);
13 static_assert(common::HIT_DATA_BIT_LENGTH <= common::BYTE_BIT_LENGTH * struct_size);
14 static_assert(sizeof(T) == struct_size);
15 auto expanded_raw_data = std::bitset<common::BYTE_BIT_LENGTH * struct_size>(raw_data.to_ullong());
16 constexpr auto shifted_bits = (struct_size * common::BYTE_BIT_LENGTH) - common::HIT_DATA_BIT_LENGTH;
17 expanded_raw_data = expanded_raw_data << shifted_bits;
18 return std::bit_cast<T>(expanded_raw_data.to_ullong());
19 }
20 struct HitDataCompact
21 {
22 uint16_t : 16;
23 uint16_t tdc : 8;
24 uint16_t channel_num : 6;
25 uint16_t is_over_threshold : 1;
26 uint16_t flag : 1;
27 uint32_t bc_id : 12;
28 uint32_t adc : 10;
29 uint32_t vmm_id : 5;
30 uint32_t offset : 5;
31 };
32
33 struct MarkerDataCompact
34 {
35 uint16_t : 16;
36 uint16_t timestamp_low_bits : common::SRS_TIMESTAMP_LOW_BIT_LENGTH;
37 uint16_t vmm_id : 5;
38 uint16_t flag : 1;
39 uint32_t timestamp_high_bits : common::SRS_TIMESTAMP_HIGH_BIT_LENGTH;
40 };
41
42 void array_to_marker(const DataElementType& raw_data, MarkerData& marker_data)
43 {
44 auto marker_data_compact = convert_to<MarkerDataCompact>(raw_data);
45
46 auto timestamp_high_bits = std::bitset<common::SRS_TIMESTAMP_HIGH_BIT_LENGTH>(
47 static_cast<uint32_t>(marker_data_compact.timestamp_high_bits));
48 auto timestamp_low_bits = std::bitset<common::SRS_TIMESTAMP_LOW_BIT_LENGTH>(
49 static_cast<uint32_t>(marker_data_compact.timestamp_low_bits));
50 marker_data.srs_timestamp = static_cast<decltype(marker_data.srs_timestamp)>(
51 common::merge_bits(timestamp_high_bits, timestamp_low_bits).to_ullong());
52 marker_data.vmm_id = static_cast<decltype(marker_data.vmm_id)>(marker_data_compact.vmm_id);
53 }
54
55 void array_to_hit(const DataElementType& raw_data, HitData& hit_data)
56 {
57 auto hit_data_compact = convert_to<HitDataCompact>(raw_data);
58
59 hit_data.is_over_threshold =
60 static_cast<decltype(hit_data.is_over_threshold)>(hit_data_compact.is_over_threshold);
61 hit_data.channel_num = static_cast<decltype(hit_data.channel_num)>(hit_data_compact.channel_num);
62 hit_data.tdc = static_cast<decltype(hit_data.tdc)>(hit_data_compact.tdc);
63 hit_data.offset = static_cast<decltype(hit_data.offset)>(hit_data_compact.offset);
64 hit_data.vmm_id = static_cast<decltype(hit_data.vmm_id)>(hit_data_compact.vmm_id);
65 hit_data.adc = static_cast<decltype(hit_data.adc)>(hit_data_compact.adc);
66 hit_data.bc_id = static_cast<decltype(hit_data.bc_id)>(hit_data_compact.bc_id);
67 hit_data.bc_id = common::gray_to_binary(hit_data.bc_id);
68 }
69 }; // namespace
70
71 // NOLINTNEXTLINE(readability-static-accessed-through-instance)
72 auto StructDeserializer::generate_coro(asio::any_io_executor /*unused*/) -> CoroType
73 {
74 InputType temp_data{};
75 while (true)
76 {
77 if (not temp_data.empty())
78 {
79 reset();
80 convert(temp_data);
81 }
82 // spdlog::info("size: {}", output_data_.hit_data.size());
83 auto data = co_yield (&output_data_);
84 if (data.has_value())
85 {
86 temp_data = data.value();
87 // spdlog::info("get data size: {}", temp_data.size());
88 }
89 else
90 {
91 spdlog::debug("Shutting down struct deserializer.");
92 co_return;
93 }
94 }
95 }
96
97 // thread safe
98 auto StructDeserializer::convert(std::string_view binary_data) -> std::size_t
99 {
100 auto deserialize_to = zpp::bits::in{ binary_data, zpp::bits::endian::network{}, zpp::bits::no_size{} };
101
102 auto read_bytes = binary_data.size() * sizeof(BufferElementType);
103 constexpr auto header_bytes = sizeof(output_data_.header);
104 constexpr auto element_bytes = common::HIT_DATA_BIT_LENGTH / common::BYTE_BIT_LENGTH;
105 auto vector_size = (read_bytes - header_bytes) / element_bytes;
106 if (vector_size < 0)
107 {
108 throw std::runtime_error("Deserialization: Wrong header type!");
109 }
110
111 // locking mutex to prevent data racing
112 receive_raw_data_.resize(vector_size);
113 std::ranges::fill(receive_raw_data_, 0);
114 deserialize_to(output_data_.header, receive_raw_data_).or_throw();
117
118 auto translated_size = receive_raw_data_.size();
119 receive_raw_data_.clear();
120
121 return translated_size;
122 }
123
125 {
126 for (const auto& element : receive_raw_data_)
127 {
128 // spdlog::info("raw data: {:x}", element.to_ullong());
129 if (auto is_hit = check_is_hit(element); is_hit)
130 {
131 auto& hit_data = struct_data.hit_data.emplace_back();
132 array_to_hit(element, hit_data);
133 }
134 else
135 {
136 auto& marker_data = struct_data.marker_data.emplace_back();
137 array_to_marker(element, marker_data);
138 }
139 }
140 }
142 {
143 // reverse byte order of each element.
144 // TODO: This is current due to a bug from zpp_bits. The reversion is not needed if it's fixed.
145 for (auto& element : receive_raw_data_)
146 {
147 element = common::byte_swap(element);
148 }
149 }
150
151} // namespace srs
asio::experimental::coro< OutputType(std::optional< InputType >)> CoroType
std::bitset< common::HIT_DATA_BIT_LENGTH > DataElementType
void translate_raw_data(StructData &struct_data)
static auto check_is_hit(const DataElementType &element) -> bool
auto convert(std::string_view binary_data) -> std::size_t
auto generate_coro(asio::any_io_executor) -> CoroType
auto data() const -> const auto &
char BufferElementType
constexpr auto SRS_TIMESTAMP_LOW_BIT_LENGTH
constexpr auto BYTE_BIT_LENGTH
constexpr auto HIT_DATA_BIT_LENGTH
constexpr auto SRS_TIMESTAMP_HIGH_BIT_LENGTH
constexpr auto gray_to_binary(T gray_val)
constexpr auto merge_bits(const std::bitset< high_size > &high_bits, const std::bitset< low_size > &low_bits) -> std::bitset< high_size+low_size >
constexpr auto byte_swap(const std::bitset< bit_size > &bits)
std::vector< MarkerData > marker_data
Marker data.
std::vector< HitData > hit_data
Hit data.