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