1 #ifndef mu2e_artdaq_core_Overlays_ArtFragmentReader_hh
2 #define mu2e_artdaq_core_Overlays_ArtFragmentReader_hh
12 #include "artdaq-core/Data/Fragment.hh"
13 #include "mu2e-artdaq-core/Overlays/ArtFragment.hh"
18 #include <unordered_map>
22 class ArtFragmentReader;
24 std::ostream &operator<<(std::ostream &, ArtFragmentReader
const &);
33 enum class PacketType : uint8_t
42 const int format_version = 6;
52 uint8_t PacketType : 4;
55 uint8_t SubsystemID : 3;
58 uint16_t PacketCount : 11;
61 uint16_t TimestampLow;
63 uint16_t TimestampMed;
65 uint16_t TimestampHigh;
68 uint8_t FormatVersion;
91 uint64_t GetTimestamp()
const {
return static_cast<uint64_t
>(TimestampLow) + (static_cast<uint64_t>(TimestampMed) << 16) + (static_cast<uint64_t>(TimestampHigh) << 32); }
104 uint16_t ADC01()
const {
return ADC01A + (ADC01B << 4); }
107 uint16_t ADC02()
const {
return ADC02A + (ADC02B << 8); }
113 uint16_t ADC05()
const {
return ADC05A + (ADC05B << 4); }
116 uint16_t ADC06()
const {
return ADC06A + (ADC06B << 8); }
122 uint16_t ADC09()
const {
return ADC09A + (ADC09B << 4); }
125 uint16_t ADC10()
const {
return ADC10A + (ADC10B << 8); }
131 uint16_t ADC13()
const {
return ADC13A + (ADC13B << 4); }
134 uint16_t ADC14()
const {
return ADC14A + (ADC14B << 8); }
136 uint16_t unused1 : 4;
137 uint16_t PreprocessingFlags : 8;
169 , PreprocessingFlags(0)
172 std::array<adc_t, 15> Waveform()
const
174 std::array<adc_t, 15> output;
185 output[10] = ADC10();
188 output[13] = ADC13();
189 output[14] = ADC14();
193 void SetWaveform(
size_t index, adc_t waveform)
198 ADC00 = waveform & 0xFFF;
201 ADC01A = waveform & 0xF;
202 ADC01B = (waveform >> 4) & 0xFF;
205 ADC02A = waveform & 0xFF;
206 ADC02B = (waveform >> 8) & 0xF;
209 ADC03 = waveform & 0xFFF;
212 ADC04 = waveform & 0xFFF;
215 ADC05A = waveform & 0xF;
216 ADC05B = (waveform >> 4) & 0xFF;
219 ADC06A = waveform & 0xFF;
220 ADC06B = (waveform >> 8) & 0xF;
223 ADC07 = waveform & 0xFFF;
226 ADC08 = waveform & 0xFFF;
229 ADC09A = waveform & 0xF;
230 ADC09B = (waveform >> 4) & 0xFF;
233 ADC10A = waveform & 0xFF;
234 ADC10B = (waveform >> 8) & 0xF;
237 ADC11 = waveform & 0xFFF;
240 ADC12 = waveform & 0xFFF;
243 ADC13A = waveform & 0xF;
244 ADC13B = (waveform >> 4) & 0xFF;
247 ADC14A = waveform & 0xFF;
248 ADC14B = (waveform >> 8) & 0xF;
256 uint16_t NumberOfHits;
264 uint16_t BoardID : 10;
265 uint16_t ChannelStatusFlagsA : 6;
266 uint16_t ChannelStatusFlagsB : 14;
270 : BoardID(0), ChannelStatusFlagsA(0), ChannelStatusFlagsB(0), unused(0) {}
275 uint16_t ChannelNumber : 6;
276 uint16_t DIRACA : 10;
280 uint8_t NumberOfSamples;
281 uint8_t IndexOfMaxDigitizerSample;
284 : ChannelNumber(0), DIRACA(0), DIRACB(0), ErrorFlags(0), Time(0), NumberOfSamples(0), IndexOfMaxDigitizerSample(0) {}
290 uint8_t PacketType : 4;
291 uint8_t ControllerID;
292 uint16_t ControllerEventWordCount;
293 uint8_t ActiveFEBFlags2;
295 uint8_t ActiveFEBFlags0;
296 uint8_t ActiveFEBFlags1;
299 uint16_t TriggerCount;
309 , ControllerEventWordCount(0)
327 uint16_t HitTime : 10;
328 uint16_t NumSamples : 6;
329 uint8_t WaveformSample0;
330 uint8_t WaveformSample1;
331 uint8_t WaveformSample2;
332 uint8_t WaveformSample3;
333 uint8_t WaveformSample4;
334 uint8_t WaveformSample5;
335 uint8_t WaveformSample6;
336 uint8_t WaveformSample7;
349 , WaveformSample7(0) {}
350 std::array<unsigned int, 8> Waveform()
const
352 std::array<unsigned int, 8> output;
353 output[0] = WaveformSample0;
354 output[1] = WaveformSample1;
355 output[2] = WaveformSample2;
356 output[3] = WaveformSample3;
357 output[4] = WaveformSample4;
358 output[5] = WaveformSample5;
359 output[6] = WaveformSample6;
360 output[7] = WaveformSample7;
371 if (block_num >= block_count())
373 TLOG(TLVL_ERROR) <<
"Requested block " << block_num <<
" is outside the allowed range! (" << block_count() <<
")";
376 if (blockSizeBytes(block_num) <
sizeof(DataBlockHeader))
378 TLOG(TLVL_ERROR) <<
"Data block size indicates that it does not contain a complete DataBlockHeader! This data is probably corrupt!";
381 return reinterpret_cast<const DataBlockHeader *
>(dataAtBlockIndex(block_num));
384 const TrackerDataPacket *GetTrackerData(
size_t block_num)
386 auto hdr = GetHeader(block_num);
387 if (hdr ==
nullptr)
return nullptr;
388 if (hdr->SubsystemID != 0)
390 TLOG(TLVL_ERROR) <<
"Trying to get Tracker data packet from non-Tracker DataBlock!";
393 if (blockSizeBytes(block_num) <
sizeof(DataBlockHeader) +
sizeof(TrackerDataPacket))
395 TLOG(TLVL_ERROR) <<
"Data Block size indicates that Tracker Data is not present! This event is probably corrupt!";
398 return reinterpret_cast<const TrackerDataPacket *
>(hdr + 1);
401 const CalorimeterDataPacket *GetCalorimeterData(
size_t block_num)
403 auto hdr = GetHeader(block_num);
404 if (hdr ==
nullptr)
return nullptr;
405 if (hdr->SubsystemID != 1)
407 TLOG(TLVL_ERROR) <<
"Trying to get Calorimeter data packet from non-Calorimeter DataBlock!";
410 auto pkt =
reinterpret_cast<const CalorimeterDataPacket *
>(hdr + 1);
412 if (blockSizeBytes(block_num) <
sizeof(DataBlockHeader) +
sizeof(CalorimeterDataPacket) +
sizeof(CalorimeterBoardID) +
sizeof(uint16_t) * (pkt->NumberOfHits +
sizeof(CalorimeterHitReadoutPacket)))
414 TLOG(TLVL_ERROR) <<
"DataBlock size and Calorimeter header indicate that this DataBlock does not contain a complete Calorimeter event! This data is probably corrupt!";
421 const uint16_t *GetCalorimeterHitIndex(
size_t block_num,
size_t hit_num)
423 auto data_pkt = GetCalorimeterData(block_num);
424 if (data_pkt ==
nullptr)
return nullptr;
425 if (hit_num >= data_pkt->NumberOfHits)
427 TLOG(TLVL_ERROR) <<
"Requested hit index " << hit_num <<
" is greater than the maximum (" << (data_pkt->NumberOfHits - 1) <<
")!";
431 return reinterpret_cast<const uint16_t *
>(data_pkt + 1) + hit_num;
434 const CalorimeterBoardID *GetCalorimeterBoardID(
size_t block_num)
436 auto data_pkt = GetCalorimeterData(block_num);
437 if (data_pkt ==
nullptr)
return nullptr;
439 return reinterpret_cast<const CalorimeterBoardID *
>(
reinterpret_cast<const uint16_t *
>(data_pkt + 1) + data_pkt->NumberOfHits);
442 const CalorimeterHitReadoutPacket *GetCalorimeterReadoutPacket(
size_t block_num,
size_t hit_num)
444 auto end_ptr =
reinterpret_cast<const uint8_t *
>(dataAtBlockIndex(block_num)) + blockSizeBytes(block_num);
446 auto data_pkt = GetCalorimeterData(block_num);
447 if (data_pkt ==
nullptr)
return nullptr;
448 if (hit_num >= data_pkt->NumberOfHits)
450 TLOG(TLVL_ERROR) <<
"Requested Hit Readout Packet at index " << hit_num <<
", but maximum index is " << (data_pkt->NumberOfHits - 1) <<
"!";
454 if (ReadoutPacketPointerCache[block_num].size() == 0)
456 auto ptr =
reinterpret_cast<const CalorimeterHitReadoutPacket *
>(GetCalorimeterBoardID(block_num) + 1);
457 if (ptr ==
nullptr)
return nullptr;
458 if (reinterpret_cast<const uint8_t *>(ptr) > end_ptr)
460 TLOG(TLVL_ERROR) <<
"Fell off the end of the DataBlock while processing CalorimeterHitReadoutPackets!";
463 ReadoutPacketPointerCache[block_num].push_back(ptr);
466 while (ReadoutPacketPointerCache[block_num].size() <= hit_num)
468 auto last_ptr = ReadoutPacketPointerCache[block_num].back();
469 auto ptr =
reinterpret_cast<const CalorimeterHitReadoutPacket *
>(
reinterpret_cast<const uint16_t *
>(last_ptr + 1) + last_ptr->NumberOfSamples);
470 if (reinterpret_cast<const uint8_t *>(ptr) > end_ptr)
472 TLOG(TLVL_ERROR) <<
"Fell off the end of the DataBlock while processing CalorimeterHitReadoutPackets!";
475 ReadoutPacketPointerCache[block_num].push_back(ptr);
477 return ReadoutPacketPointerCache[block_num][hit_num];
480 const uint16_t *GetCalorimeterReadoutSample(
size_t block_num,
size_t hit_num,
size_t sample_num)
482 auto pkt = GetCalorimeterReadoutPacket(block_num, hit_num);
483 if (pkt ==
nullptr)
return nullptr;
484 if (sample_num >= pkt->NumberOfSamples)
486 TLOG(TLVL_ERROR) <<
"Requested sample index " << sample_num <<
" is greater than the maximum allowed (" << (pkt->NumberOfSamples - 1) <<
")!";
489 return reinterpret_cast<const uint16_t *
>(pkt + 1) + sample_num;
492 const CRVROCStatusPacket *GetCRVROCStatusPacket(
size_t block_num)
494 auto hdr = GetHeader(block_num);
495 if (hdr ==
nullptr)
return nullptr;
496 if (hdr->SubsystemID != 2)
498 TLOG(TLVL_ERROR) <<
"Trying to get CRV data packet from non-CRV DataBlock!";
502 if (blockSizeBytes(block_num) <
sizeof(DataBlockHeader) +
sizeof(CRVROCStatusPacket))
504 TLOG(TLVL_ERROR) <<
"Data Block size indicates that CRV ROC Status Packet is not present! This event is probably corrupt!";
508 auto crv_hdr =
reinterpret_cast<const CRVROCStatusPacket *
>(hdr + 1);
509 if (blockSizeBytes(block_num) <
sizeof(DataBlockHeader) + crv_hdr->ControllerEventWordCount)
511 TLOG(TLVL_ERROR) <<
"Inconsistency detected between Data Block Size (" << blockSizeBytes(block_num) <<
") and CRV header's declared size (" << (
sizeof(DataBlockHeader) + crv_hdr->ControllerEventWordCount) <<
")! This event is probably corrupt!";
518 size_t GetCRVHitCount(
size_t block_num)
520 auto hdr = GetCRVROCStatusPacket(block_num);
521 if (hdr ==
nullptr)
return 0;
523 size_t hit_bytes = hdr->ControllerEventWordCount -
sizeof(CRVROCStatusPacket);
525 size_t packet_count = hit_bytes /
sizeof(CRVHitReadoutPacket);
527 auto hit_packet =
reinterpret_cast<const CRVHitReadoutPacket *
>(hdr + 1);
528 if (*reinterpret_cast<const uint8_t *>(hit_packet + (packet_count - 1)) == 0)
536 const CRVHitReadoutPacket *GetCRVHitReadoutPacket(
size_t block_num,
size_t hit_idx)
538 auto hdr = GetCRVROCStatusPacket(block_num);
539 if (hdr ==
nullptr)
return nullptr;
541 auto hit_count = GetCRVHitCount(block_num);
542 if (hit_idx >= hit_count)
544 TLOG(TLVL_ERROR) <<
"Requested hit index " << hit_idx <<
" is greater than the last hit index in this DataBlock (" << (hit_count - 1) <<
")!";
548 return reinterpret_cast<const CRVHitReadoutPacket *
>(hdr + 1) + hit_idx;
552 std::unordered_map<size_t, std::deque<const CalorimeterHitReadoutPacket *>> ReadoutPacketPointerCache;