SRS-control 0.1.4
Loading...
Searching...
No Matches
StructDeserializer.cpp
Go to the documentation of this file.
7#include <algorithm>
8#include <bitset>
9#include <cstddef>
10#include <cstdint>
11#include <expected>
12#include <string_view>
13#include <zpp_bits.h>
14
15namespace srs::process
16{
17 namespace
18 {
19 using DataElementType = StructDeserializer::DataElementType;
20
21 template <typename T>
22 auto convert_to(const DataElementType& raw_data) -> T
23 {
24 constexpr auto struct_size = sizeof(uint64_t);
25 static_assert(common::HIT_DATA_BIT_LENGTH <= common::BYTE_BIT_LENGTH * struct_size);
26 static_assert(sizeof(T) == struct_size);
27 auto expanded_raw_data = std::bitset<common::BYTE_BIT_LENGTH * struct_size>(raw_data.to_ullong());
28 constexpr auto shifted_bits = (struct_size * common::BYTE_BIT_LENGTH) - common::HIT_DATA_BIT_LENGTH;
29 expanded_raw_data = expanded_raw_data << shifted_bits;
30 return std::bit_cast<T>(expanded_raw_data.to_ullong());
31 }
32 struct HitDataCompact
33 {
34 uint16_t : 16;
35 uint16_t tdc : 8;
36 uint16_t channel_num : 6;
37 uint16_t is_over_threshold : 1;
38 uint16_t flag : 1;
39 uint32_t bc_id : 12;
40 uint32_t adc : 10;
41 uint32_t vmm_id : 5;
42 uint32_t offset : 5;
43 };
44
45 struct MarkerDataCompact
46 {
47 uint16_t : 16;
48 uint16_t timestamp_low_bits : common::SRS_TIMESTAMP_LOW_BIT_LENGTH;
49 uint16_t vmm_id : 5;
50 uint16_t flag : 1;
51 uint32_t timestamp_high_bits : common::SRS_TIMESTAMP_HIGH_BIT_LENGTH;
52 };
53
54 void array_to_marker(const DataElementType& raw_data, MarkerData& marker_data)
55 {
56 auto marker_data_compact = convert_to<MarkerDataCompact>(raw_data);
57
58 auto timestamp_high_bits = std::bitset<common::SRS_TIMESTAMP_HIGH_BIT_LENGTH>(
59 static_cast<uint32_t>(marker_data_compact.timestamp_high_bits));
60 auto timestamp_low_bits = std::bitset<common::SRS_TIMESTAMP_LOW_BIT_LENGTH>(
61 static_cast<uint32_t>(marker_data_compact.timestamp_low_bits));
62 marker_data.srs_timestamp = static_cast<decltype(marker_data.srs_timestamp)>(
63 common::merge_bits(timestamp_high_bits, timestamp_low_bits).to_ullong());
64 marker_data.vmm_id = static_cast<decltype(marker_data.vmm_id)>(marker_data_compact.vmm_id);
65 }
66
67 void array_to_hit(const DataElementType& raw_data, HitData& hit_data)
68 {
69 auto hit_data_compact = convert_to<HitDataCompact>(raw_data);
70
71 hit_data.is_over_threshold =
72 static_cast<decltype(hit_data.is_over_threshold)>(hit_data_compact.is_over_threshold);
73 hit_data.channel_num = static_cast<decltype(hit_data.channel_num)>(hit_data_compact.channel_num);
74 hit_data.tdc = static_cast<decltype(hit_data.tdc)>(hit_data_compact.tdc);
75 hit_data.offset = static_cast<decltype(hit_data.offset)>(hit_data_compact.offset);
76 hit_data.vmm_id = static_cast<decltype(hit_data.vmm_id)>(hit_data_compact.vmm_id);
77 hit_data.adc = static_cast<decltype(hit_data.adc)>(hit_data_compact.adc);
78 hit_data.bc_id = static_cast<decltype(hit_data.bc_id)>(hit_data_compact.bc_id);
79 hit_data.bc_id = common::gray_to_binary(hit_data.bc_id);
80 }
81 }; // namespace
82
84 : ConverterTask{ "Struct deserializer", raw, n_lines }
85 {
86 raw_body_part_data_.resize(n_lines);
87 output_data_.resize(n_lines);
88 }
89
90 // thread safe
91 auto StructDeserializer::convert(std::string_view binary_data,
92 StructData& output_data,
93 ReceiveDataSquence& body_part_data) -> std::expected<std::size_t, std::string_view>
94 {
95 auto deserialize_to = zpp::bits::in{ binary_data, zpp::bits::endian::network{}, zpp::bits::no_size{} };
96
97 auto read_bytes = binary_data.size() * sizeof(BufferElementType);
98 constexpr auto header_bytes = sizeof(output_data.header);
99 constexpr auto element_bytes = common::HIT_DATA_BIT_LENGTH / common::BYTE_BIT_LENGTH;
100 if (read_bytes <= header_bytes)
101 {
102 return std::unexpected{ "Deserialization: The size of the binary data is too small!" };
103 }
104 auto vector_size = (read_bytes - header_bytes) / element_bytes;
105 if (vector_size == 0)
106 {
107 return std::unexpected{ "Deserialization: Cannot read the header correctly!" };
108 }
109
110 // locking mutex to prevent data racing
111 body_part_data.resize(vector_size);
112 std::ranges::fill(body_part_data, 0);
113 deserialize_to(output_data.header, body_part_data).or_throw();
114 byte_reverse_data_sq(body_part_data);
115 translate_raw_data(output_data, body_part_data);
116
117 return body_part_data.size();
118 }
119
121 {
122 for (const auto& element : receive_raw_data)
123 {
124 // spdlog::info("raw data: {:x}", element.to_ullong());
125 if (auto is_hit = check_is_hit(element); is_hit)
126 {
127 auto& hit_data = struct_data.hit_data.emplace_back();
128 array_to_hit(element, hit_data);
129 }
130 else
131 {
132 auto& marker_data = struct_data.marker_data.emplace_back();
133 array_to_marker(element, marker_data);
134 }
135 }
136 }
138 {
139 // reverse byte order of each element.
140 // TODO: This is current due to a bug from zpp_bits. The reversion is not needed if it's fixed.
141 for (auto& element : receive_raw_data)
142 {
143 element = common::byte_swap(element);
144 }
145 }
146
147} // namespace srs::process
ConverterTask(std::string_view name, DataConvertOptions prev_convert, std::size_t n_lines=1)
std::vector< StructData > output_data_
static void translate_raw_data(StructData &struct_data, ReceiveDataSquence &receive_raw_data)
static auto convert(std::string_view binary_data, StructData &output, ReceiveDataSquence &body_part_data) -> std::expected< std::size_t, std::string_view >
std::vector< DataElementType > ReceiveDataSquence
std::bitset< common::HIT_DATA_BIT_LENGTH > DataElementType
static auto check_is_hit(const DataElementType &element) -> bool
std::vector< ReceiveDataSquence > raw_body_part_data_
static void byte_reverse_data_sq(ReceiveDataSquence &receive_raw_data)
constexpr auto gray_to_binary(T gray_val)
constexpr auto SRS_TIMESTAMP_LOW_BIT_LENGTH
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_BIT_LENGTH
constexpr auto HIT_DATA_BIT_LENGTH
constexpr auto SRS_TIMESTAMP_HIGH_BIT_LENGTH
constexpr auto byte_swap(const std::bitset< bit_size > &bits)
char BufferElementType
std::vector< MarkerData > marker_data
Marker data.
std::vector< HitData > hit_data
Hit data.