DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
WIBFrame.hpp
Go to the documentation of this file.
1
11#ifndef FDDETDATAFORMATS_INCLUDE_FDDETDATAFORMATS_WIBFRAME_HPP_
12#define FDDETDATAFORMATS_INCLUDE_FDDETDATAFORMATS_WIBFRAME_HPP_
13
14#include <bitset>
15#include <iostream>
16#include <vector>
17#include <stdexcept>
18#include <cstdint>
19
21
22using word_t = uint32_t; // NOLINT(build/unsigned)
23using adc_t = uint16_t; // NOLINT(build/unsigned)
24
29{
30 word_t sof : 8, version : 5, fiber_no : 3, crate_no : 5, slot_no : 3, reserved_1 : 8;
31 word_t mm : 1, oos : 1, reserved_2 : 14, wib_errors : 16;
34
35 uint64_t get_timestamp() const // NOLINT(build/unsigned)
36 {
37 uint64_t timestamp = timestamp_1 | (static_cast<uint64_t>(timestamp_2) << 32); // NOLINT(build/unsigned)
38 if (!z) {
39 timestamp |= static_cast<uint64_t>(wib_counter_1) << 48; // NOLINT(build/unsigned)
40 }
41 return timestamp;
42 }
43 uint16_t get_wib_counter() const { return z ? wib_counter_1 : 0; } // NOLINT(build/unsigned)
44
45 void set_timestamp(const uint64_t new_timestamp) // NOLINT(build/unsigned)
46 {
47 timestamp_1 = new_timestamp;
48 timestamp_2 = new_timestamp >> 32;
49 if (!z) {
50 wib_counter_1 = new_timestamp >> 48;
51 }
52 }
53 void set_wib_counter(const uint16_t new_wib_counter) // NOLINT(build/unsigned)
54 {
55 if (z) {
56 wib_counter_1 = new_wib_counter;
57 }
58 }
59
60 // Print functions for debugging.
61 std::ostream& print_hex(std::ostream& o) const
62 {
63 return o << std::hex << "SOF:" << sof << " version:" << version << " fiber:" << fiber_no << " slot:" << slot_no
64 << " crate:" << crate_no << " mm:" << mm << " oos:" << oos << " wib_errors:" << wib_errors
65 << " timestamp: " << get_timestamp() << std::dec << '\n';
66 }
67
68 std::ostream& print_bits(std::ostream& o) const
69 {
70 return o << "SOF:" << std::bitset<8>(sof) << " version:" << std::bitset<5>(version)
71 << " fiber:" << std::bitset<3>(fiber_no) << " slot:" << std::bitset<5>(slot_no)
72 << " crate:" << std::bitset<3>(crate_no) << " mm:" << bool(mm) << " oos:" << bool(oos)
73 << " wib_errors:" << std::bitset<16>(wib_errors) << " timestamp: " << get_timestamp() << '\n'
74 << " Z: " << z << '\n';
75 }
76};
77
78inline std::ostream&
79operator<<(std::ostream& o, WIBHeader const& h)
80{
81 return o << "SOF:" << unsigned(h.sof) << " version:" << unsigned(h.version) << " fiber:" << unsigned(h.fiber_no)
82 << " slot:" << unsigned(h.slot_no) << " crate:" << unsigned(h.crate_no) << " mm:" << unsigned(h.mm)
83 << " oos:" << unsigned(h.oos) << " wib_errors:" << unsigned(h.wib_errors)
84 << " timestamp: " << h.get_timestamp() << '\n';
85}
86
91{
95 word_t hdr_1 : 4, hdr_3 : 4, hdr_2 : 4, hdr_4 : 4, hdr_5 : 4, hdr_7 : 4, hdr_6 : 4, hdr_8 : 4;
96
97 uint16_t get_checksum_a() const // NOLINT(build/unsigned)
98 {
99 return static_cast<uint16_t>(checksum_a_1) | (checksum_a_2 << 8); // NOLINT(build/unsigned)
100 }
101 uint16_t get_checksum_b() const // NOLINT(build/unsigned)
102 {
103 return static_cast<uint16_t>(checksum_b_1) | (checksum_b_2 << 8); // NOLINT(build/unsigned)
104 }
105 uint8_t get_hdr(const uint8_t i) const // NOLINT(build/unsigned)
106 {
107 switch (i) {
108 case 1:
109 return hdr_1;
110 case 2:
111 return hdr_2;
112 case 3:
113 return hdr_3;
114 case 4:
115 return hdr_4;
116 case 5:
117 return hdr_5;
118 case 6:
119 return hdr_6;
120 case 7:
121 return hdr_7;
122 case 8:
123 return hdr_8;
124 }
125 return 0;
126 }
127
128 void set_checksum_a(const uint16_t new_checksum_a) // NOLINT(build/unsigned)
129 {
130 checksum_a_1 = new_checksum_a;
131 checksum_a_2 = new_checksum_a >> 8;
132 }
133 void set_checksum_b(const uint16_t new_checksum_b) // NOLINT(build/unsigned)
134 {
135 checksum_b_1 = new_checksum_b;
136 checksum_b_2 = new_checksum_b >> 8;
137 }
138 void set_hdr(const uint8_t i, const uint8_t new_hdr) // NOLINT(build/unsigned)
139 {
140 switch (i) {
141 case 1:
142 hdr_1 = new_hdr;
143 break;
144 case 2:
145 hdr_2 = new_hdr;
146 break;
147 case 3:
148 hdr_3 = new_hdr;
149 break;
150 case 4:
151 hdr_4 = new_hdr;
152 break;
153 case 5:
154 hdr_5 = new_hdr;
155 break;
156 case 6:
157 hdr_6 = new_hdr;
158 break;
159 case 7:
160 hdr_7 = new_hdr;
161 break;
162 case 8:
163 hdr_8 = new_hdr;
164 break;
165 }
166 }
167
168 // Print functions for debugging.
169 std::ostream& print_hex(std::ostream& o) const
170 {
171 o << std::hex << "s1_error:" << s1_error << " s2_error:" << s2_error << " checksum_a1:" << checksum_a_1
172 << " checksum_b1:" << checksum_b_1 << " checksum_a2:" << checksum_a_2 << " checksum_b1:" << checksum_b_2
173 << " coldata_convert_count:" << coldata_convert_count << " error_register:" << error_register
174 << " hdr_1:" << hdr_1 << " hdr_2:" << hdr_2 << " hdr_3:" << hdr_3 << " hdr_4:" << hdr_4 << " hdr_5:" << hdr_5
175 << " hdr_6:" << hdr_6 << " hdr_7:" << hdr_7 << " hdr_8:" << hdr_8;
176 return o << '\n';
177 }
178 std::ostream& print_bits(std::ostream& o) const
179 {
180 o << "s1_error:" << std::bitset<4>(s1_error) << " s2_error:" << std::bitset<4>(s2_error)
181 << " checksum_a1:" << std::bitset<8>(checksum_a_1) << " checksum_b1:" << std::bitset<8>(checksum_b_1)
182 << " checksum_a2:" << std::bitset<8>(checksum_a_2) << " checksum_b2:" << std::bitset<8>(checksum_b_2)
183 << " coldata_convert_count:" << std::bitset<16>(coldata_convert_count)
184 << " error_register:" << std::bitset<16>(error_register) << " hdr_1:" << std::bitset<8>(hdr_1)
185 << " hdr_2:" << std::bitset<8>(hdr_2) << " hdr_3:" << std::bitset<8>(hdr_3) << " hdr_4:" << std::bitset<8>(hdr_4)
186 << " hdr_5:" << std::bitset<8>(hdr_5) << " hdr_6:" << std::bitset<8>(hdr_6) << " hdr_7:" << std::bitset<8>(hdr_7)
187 << " hdr_8:" << std::bitset<8>(hdr_8);
188 return o << '\n';
189 }
190};
191
192inline std::ostream&
193operator<<(std::ostream& o, ColdataHeader const& hdr)
194{
195 o << "s1_error:" << unsigned(hdr.s1_error) << " s2_error:" << unsigned(hdr.s2_error)
196 << " checksum_a1:" << unsigned(hdr.checksum_a_1) << " checksum_b1:" << unsigned(hdr.checksum_b_1)
197 << " checksum_a2:" << unsigned(hdr.checksum_a_2) << " checksum_b1:" << unsigned(hdr.checksum_b_2)
198 << " coldata_convert_count:" << unsigned(hdr.coldata_convert_count)
199 << " error_register:" << unsigned(hdr.error_register) << " hdr_1:" << unsigned(hdr.hdr_1)
200 << " hdr_2:" << unsigned(hdr.hdr_2) << " hdr_3:" << unsigned(hdr.hdr_3) << " hdr_4:" << unsigned(hdr.hdr_4)
201 << " hdr_5:" << unsigned(hdr.hdr_5) << " hdr_6:" << unsigned(hdr.hdr_6) << " hdr_7:" << unsigned(hdr.hdr_7)
202 << " hdr_8:" << unsigned(hdr.hdr_8);
203 return o << '\n';
204}
205
210{
211 static constexpr int s_num_ch_per_seg = 8;
212
213 // This struct contains three words of ADC values that form the main repeating
214 // pattern in the COLDATA block.
218
219 uint16_t get_channel(const uint8_t adc, const uint8_t ch) const // NOLINT(build/unsigned)
220 {
221 if (adc % 2 == 0) {
222 switch (ch % 4) {
223 case 0:
224 return adc0ch0_1 | adc0ch0_2 << 8;
225 case 1:
226 return adc0ch1_1 | adc0ch1_2 << 4;
227 case 2:
228 return adc0ch2_1 | adc0ch2_2 << 8;
229 case 3:
230 return adc0ch3_1 | adc0ch3_2 << 4;
231 }
232 } else if (adc % 2 == 1) {
233 switch (ch % 4) {
234 case 0:
235 return adc1ch0_1 | adc1ch0_2 << 8;
236 case 1:
237 return adc1ch1_1 | adc1ch1_2 << 4;
238 case 2:
239 return adc1ch2_1 | adc1ch2_2 << 8;
240 case 3:
241 return adc1ch3_1 | adc1ch3_2 << 4;
242 }
243 }
244 throw std::range_error("Supplied WIB channel index is out of the allowed range.");
245 return 0;
246 }
247
248 void set_channel(const uint8_t adc, const uint8_t ch, const uint16_t new_val) // NOLINT(build/unsigned)
249 {
250 if (adc % 2 == 0) {
251 switch (ch % 4) {
252 case 0:
253 adc0ch0_1 = new_val;
254 adc0ch0_2 = new_val >> 8;
255 break;
256 case 1:
257 adc0ch1_1 = new_val;
258 adc0ch1_2 = new_val >> 4;
259 break;
260 case 2:
261 adc0ch2_1 = new_val;
262 adc0ch2_2 = new_val >> 8;
263 break;
264 case 3:
265 adc0ch3_1 = new_val;
266 adc0ch3_2 = new_val >> 4;
267 break;
268 }
269 } else if (adc % 2 == 1) {
270 switch (ch % 4) {
271 case 0:
272 adc1ch0_1 = new_val;
273 adc1ch0_2 = new_val >> 8;
274 break;
275 case 1:
276 adc1ch1_1 = new_val;
277 adc1ch1_2 = new_val >> 4;
278 break;
279 case 2:
280 adc1ch2_1 = new_val;
281 adc1ch2_2 = new_val >> 8;
282 break;
283 case 3:
284 adc1ch3_1 = new_val;
285 adc1ch3_2 = new_val >> 4;
286 break;
287 }
288 }
289 }
290};
291
296{
297 static constexpr int s_num_seg_per_block = 8;
298 static constexpr int s_num_ch_per_adc = 8;
301
304
305 uint16_t get_channel(const uint8_t adc, const uint8_t ch) const // NOLINT(build/unsigned)
306 {
307 // Each segment houses one half (four channels) of two subsequent ADCs.
308 return segments[get_segment_index_(adc, ch)].get_channel(adc, ch);
309 }
310
311 void set_channel(const uint8_t adc, const uint8_t ch, const uint16_t new_val) // NOLINT(build/unsigned)
312 {
313 segments[get_segment_index_(adc, ch)].set_channel(adc, ch, new_val);
314 }
315
316private:
317 int get_segment_index_(const int adc, const int ch) const
318 {
319 auto segment_id = (adc / 2) * 2 + ch / 4;
320
321 if (segment_id < 0 || segment_id > s_num_seg_per_block - 1) {
322 throw std::out_of_range("ADC index out of range");
323 }
324 return segment_id;
325 }
326};
327
328inline std::ostream&
329operator<<(std::ostream& o, const ColdataBlock& block)
330{
331 o << block.head;
332
333 // Note that this is an ADC-centric view, whereas ColdataBlock uses a channel-centric view
334 o << "\t\t0\t1\t2\t3\t4\t5\t6\t7\n";
335 for (int adc = 0; adc < 8; adc++) {
336 o << "Stream " << adc << ":\t";
337 for (int ch = 0; ch < 8; ch++) {
338 o << std::hex << block.get_channel(adc, ch) << '\t';
339 }
340 o << std::dec << '\n';
341 }
342 return o;
343}
344
349{
350public:
351 static constexpr int s_num_block_per_frame = 4;
353
354 static constexpr int s_num_frame_hdr_words = sizeof(WIBHeader) / sizeof(word_t);
355 static constexpr int s_num_COLDATA_hdr_words = sizeof(ColdataHeader) / sizeof(word_t);
356 static constexpr int s_num_COLDATA_words = sizeof(ColdataBlock) / sizeof(word_t);
358 static constexpr int s_num_frame_bytes = s_num_frame_words * sizeof(word_t);
359
360 const WIBHeader* get_wib_header() const { return &m_head; }
362
363 const ColdataHeader* get_coldata_header(const unsigned block_index) const
364 {
366 return &m_blocks[block_index].head;
367 }
368 const ColdataBlock& get_block(const uint8_t b) const // NOLINT(build/unsigned)
369 {
371 return m_blocks[b];
372 }
373
374 // WIBHeader mutators
375 void set_wib_errors(const uint16_t new_wib_errors) { m_head.wib_errors = new_wib_errors; } // NOLINT(build/unsigned)
376 void set_timestamp(const uint64_t new_timestamp) { m_head.set_timestamp(new_timestamp); } // NOLINT(build/unsigned)
377
378 uint64_t get_timestamp() const { return m_head.get_timestamp(); } // NOLINT(build/unsigned)
379
380 // ColdataBlock channel accessors
381 uint16_t get_channel(const uint8_t block_num, const uint8_t adc, const uint8_t ch) const // NOLINT(build/unsigned)
382 {
384 return m_blocks[block_num].get_channel(adc, ch);
385 }
386 uint16_t get_channel(const uint8_t block_num, const uint8_t ch) const // NOLINT(build/unsigned)
387 {
390 }
391 uint16_t get_channel(const uint8_t ch) const // NOLINT(build/unsigned)
392 {
394 }
395
396 // ColdataBlock channel mutators
397 void set_channel(const uint8_t block_num, // NOLINT(build/unsigned)
398 const uint8_t adc, // NOLINT(build/unsigned)
399 const uint8_t ch, // NOLINT(build/unsigned)
400 const uint16_t new_val) // NOLINT(build/unsigned)
401 {
403 m_blocks[block_num].set_channel(adc, ch, new_val);
404 }
405 void set_channel(const uint8_t block_num, const uint8_t ch, const uint16_t new_val) // NOLINT(build/unsigned)
406 {
409 }
410 void set_channel(const uint8_t ch, const uint16_t new_val) // NOLINT(build/unsigned)
411 {
413 }
414
415 friend std::ostream& operator<<(std::ostream& o, WIBFrame const& frame);
416
417private:
418 void throw_if_invalid_block_index_(const int block_num) const
419 {
420 if (block_num < 0 || block_num > s_num_block_per_frame - 1) {
421 throw std::out_of_range("FEMB index out of range");
422 }
423 }
424
427};
428
429inline std::ostream&
430operator<<(std::ostream& o, WIBFrame const& frame)
431{
432 o << "Printing frame:" << '\n';
433 o << frame.m_head << '\n';
434 for (auto b : frame.m_blocks) {
435 o << b;
436 }
437 return o;
438}
439
440} // namespace dunedaq::fddetdataformats
441
442#endif // FDDETDATAFORMATS_INCLUDE_FDDETDATAFORMATS_WIBFRAME_HPP_
void set_timestamp(const uint64_t new_timestamp)
Definition WIBFrame.hpp:376
static constexpr int s_num_COLDATA_hdr_words
Definition WIBFrame.hpp:355
static constexpr int s_num_COLDATA_words
Definition WIBFrame.hpp:356
void set_channel(const uint8_t ch, const uint16_t new_val)
Definition WIBFrame.hpp:410
static constexpr int s_num_frame_words
Definition WIBFrame.hpp:357
friend std::ostream & operator<<(std::ostream &o, WIBFrame const &frame)
Definition WIBFrame.hpp:430
void set_wib_errors(const uint16_t new_wib_errors)
Definition WIBFrame.hpp:375
const WIBHeader * get_wib_header() const
Definition WIBFrame.hpp:360
static constexpr int s_num_frame_bytes
Definition WIBFrame.hpp:358
static constexpr int s_num_block_per_frame
Definition WIBFrame.hpp:351
uint16_t get_channel(const uint8_t block_num, const uint8_t adc, const uint8_t ch) const
Definition WIBFrame.hpp:381
void set_channel(const uint8_t block_num, const uint8_t ch, const uint16_t new_val)
Definition WIBFrame.hpp:405
static constexpr int s_num_ch_per_frame
Definition WIBFrame.hpp:352
ColdataBlock m_blocks[s_num_block_per_frame]
Definition WIBFrame.hpp:426
uint16_t get_channel(const uint8_t ch) const
Definition WIBFrame.hpp:391
static constexpr int s_num_frame_hdr_words
Definition WIBFrame.hpp:354
const ColdataBlock & get_block(const uint8_t b) const
Definition WIBFrame.hpp:368
const ColdataHeader * get_coldata_header(const unsigned block_index) const
Definition WIBFrame.hpp:363
uint16_t get_channel(const uint8_t block_num, const uint8_t ch) const
Definition WIBFrame.hpp:386
void set_channel(const uint8_t block_num, const uint8_t adc, const uint8_t ch, const uint16_t new_val)
Definition WIBFrame.hpp:397
void throw_if_invalid_block_index_(const int block_num) const
Definition WIBFrame.hpp:418
std::ostream & operator<<(std::ostream &o, TDEHeader const &tde_header)
PDS Frame with unphysical timestamp detected with ch
static constexpr int s_num_seg_per_block
Definition WIBFrame.hpp:297
void set_channel(const uint8_t adc, const uint8_t ch, const uint16_t new_val)
Definition WIBFrame.hpp:311
static constexpr int s_num_adc_per_block
Definition WIBFrame.hpp:299
static constexpr int s_num_ch_per_block
Definition WIBFrame.hpp:300
ColdataSegment segments[s_num_seg_per_block]
Definition WIBFrame.hpp:303
int get_segment_index_(const int adc, const int ch) const
Definition WIBFrame.hpp:317
uint16_t get_channel(const uint8_t adc, const uint8_t ch) const
Definition WIBFrame.hpp:305
std::ostream & print_hex(std::ostream &o) const
Definition WIBFrame.hpp:169
uint8_t get_hdr(const uint8_t i) const
Definition WIBFrame.hpp:105
void set_hdr(const uint8_t i, const uint8_t new_hdr)
Definition WIBFrame.hpp:138
void set_checksum_a(const uint16_t new_checksum_a)
Definition WIBFrame.hpp:128
void set_checksum_b(const uint16_t new_checksum_b)
Definition WIBFrame.hpp:133
std::ostream & print_bits(std::ostream &o) const
Definition WIBFrame.hpp:178
uint16_t get_channel(const uint8_t adc, const uint8_t ch) const
Definition WIBFrame.hpp:219
void set_channel(const uint8_t adc, const uint8_t ch, const uint16_t new_val)
Definition WIBFrame.hpp:248
std::ostream & print_bits(std::ostream &o) const
Definition WIBFrame.hpp:68
std::ostream & print_hex(std::ostream &o) const
Definition WIBFrame.hpp:61
void set_wib_counter(const uint16_t new_wib_counter)
Definition WIBFrame.hpp:53
void set_timestamp(const uint64_t new_timestamp)
Definition WIBFrame.hpp:45