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>
21 class ArtFragmentReader;
23 std::ostream &operator<<(std::ostream &, ArtFragmentReader
const &);
32 enum class PacketType : uint8_t
41 const int format_version = 6;
51 uint8_t PacketType : 4;
54 uint8_t SubsystemID : 3;
57 uint16_t PacketCount : 11;
60 uint16_t TimestampLow;
62 uint16_t TimestampMed;
64 uint16_t TimestampHigh;
67 uint8_t FormatVersion;
72 uint64_t GetTimestamp()
const {
return static_cast<uint64_t
>(TimestampLow) + (static_cast<uint64_t>(TimestampMed) << 16) + (static_cast<uint64_t>(TimestampHigh) << 32); }
89 uint16_t ADC05()
const {
return static_cast<uint16_t
>(ADC05A) + static_cast<uint16_t>(ADC05B << 4); }
96 uint16_t ADC10()
const {
return static_cast<uint16_t
>(ADC10A) + static_cast<uint16_t>(ADC10B << 8); }
101 uint64_t unused1 : 4;
102 uint64_t PreprocessingFlags : 8;
104 std::array<adc_t, 15> Waveform()
const
106 std::array<adc_t, 15> output;
117 output[10] = ADC10();
128 uint16_t NumberOfHits;
133 uint16_t BoardID : 10;
134 uint16_t ChannelStatusFlagsA : 6;
135 uint16_t ChannelStatusFlagsB : 14;
141 uint16_t ChannelNumber : 6;
142 uint16_t DIRACA : 10;
146 uint8_t NumberOfSamples;
147 uint8_t IndexOfMaxDigitizerSample;
153 uint8_t PacketType : 4;
154 uint8_t ControllerID;
155 uint16_t ControllerEventWordCount;
156 uint8_t ActiveFEBFlags2;
158 uint8_t ActiveFEBFlags0;
159 uint8_t ActiveFEBFlags1;
162 uint16_t TriggerCount;
172 uint16_t HitTime : 10;
173 uint16_t NumSamples : 6;
174 uint8_t WaveformSample0;
175 uint8_t WaveformSample1;
176 uint8_t WaveformSample2;
177 uint8_t WaveformSample3;
178 uint8_t WaveformSample4;
179 uint8_t WaveformSample5;
180 uint8_t WaveformSample6;
181 uint8_t WaveformSample7;
183 std::array<unsigned int, 8> Waveform()
const {
184 std::array<unsigned int, 8> output;
185 output[0] = WaveformSample0;
186 output[1] = WaveformSample1;
187 output[2] = WaveformSample2;
188 output[3] = WaveformSample3;
189 output[4] = WaveformSample4;
190 output[5] = WaveformSample5;
191 output[6] = WaveformSample6;
192 output[7] = WaveformSample7;
203 if (block_num >= block_count())
205 TLOG(TLVL_ERROR) <<
"Requested block " << block_num <<
" is outside the allowed range! (" << block_count() <<
")";
208 if (blockSizeBytes(block_num) <
sizeof(DataBlockHeader))
210 TLOG(TLVL_ERROR) <<
"Data block size indicates that it does not contain a complete DataBlockHeader! This data is probably corrupt!";
213 return reinterpret_cast<const DataBlockHeader *
>(dataAtBlockIndex(block_num));
216 const TrackerDataPacket *GetTrackerData(
size_t block_num)
218 auto hdr = GetHeader(block_num);
219 if (hdr ==
nullptr)
return nullptr;
220 if (hdr->SubsystemID != 0)
222 TLOG(TLVL_ERROR) <<
"Trying to get Tracker data packet from non-Tracker DataBlock!";
225 if (blockSizeBytes(block_num) <
sizeof(DataBlockHeader) +
sizeof(TrackerDataPacket))
227 TLOG(TLVL_ERROR) <<
"Data Block size indicates that Tracker Data is not present! This event is probably corrupt!";
230 return reinterpret_cast<const TrackerDataPacket *
>(hdr + 1);
233 const CalorimeterDataPacket *GetCalorimeterData(
size_t block_num)
235 auto hdr = GetHeader(block_num);
236 if (hdr ==
nullptr)
return nullptr;
237 if (hdr->SubsystemID != 1)
239 TLOG(TLVL_ERROR) <<
"Trying to get Calorimeter data packet from non-Calorimeter DataBlock!";
242 auto pkt =
reinterpret_cast<const CalorimeterDataPacket *
>(hdr + 1);
244 if (blockSizeBytes(block_num) <
sizeof(DataBlockHeader) +
sizeof(CalorimeterDataPacket) +
sizeof(CalorimeterBoardID) +
sizeof(uint16_t) * (pkt->NumberOfHits +
sizeof(CalorimeterHitReadoutPacket)))
246 TLOG(TLVL_ERROR) <<
"DataBlock size and Calorimeter header indicate that this DataBlock does not contain a complete Calorimeter event! This data is probably corrupt!";
253 const uint16_t *GetCalorimeterHitIndex(
size_t block_num,
size_t hit_num)
255 auto data_pkt = GetCalorimeterData(block_num);
256 if (data_pkt ==
nullptr)
return nullptr;
257 if (hit_num >= data_pkt->NumberOfHits)
259 TLOG(TLVL_ERROR) <<
"Requested hit index " << hit_num <<
" is greater than the maximum (" << (data_pkt->NumberOfHits - 1) <<
")!";
263 return reinterpret_cast<const uint16_t *
>(data_pkt + 1) + hit_num;
266 const CalorimeterBoardID *GetCalorimeterBoardID(
size_t block_num)
268 auto data_pkt = GetCalorimeterData(block_num);
269 if (data_pkt ==
nullptr)
return nullptr;
271 return reinterpret_cast<const CalorimeterBoardID *
>(
reinterpret_cast<const uint16_t *
>(data_pkt + 1) + data_pkt->NumberOfHits);
274 const CalorimeterHitReadoutPacket *GetCalorimeterReadoutPacket(
size_t block_num,
size_t hit_num)
276 auto end_ptr =
reinterpret_cast<const uint8_t *
>(dataAtBlockIndex(block_num)) + blockSizeBytes(block_num);
278 auto data_pkt = GetCalorimeterData(block_num);
279 if (data_pkt ==
nullptr)
return nullptr;
280 if (hit_num >= data_pkt->NumberOfHits)
282 TLOG(TLVL_ERROR) <<
"Requested Hit Readout Packet at index " << hit_num <<
", but maximum index is " << (data_pkt->NumberOfHits - 1) <<
"!";
286 if (ReadoutPacketPointerCache[block_num].size() == 0)
288 auto ptr =
reinterpret_cast<const CalorimeterHitReadoutPacket *
>(GetCalorimeterBoardID(block_num) + 1);
289 if (ptr ==
nullptr)
return nullptr;
290 if (reinterpret_cast<const uint8_t *>(ptr) > end_ptr)
292 TLOG(TLVL_ERROR) <<
"Fell off the end of the DataBlock while processing CalorimeterHitReadoutPackets!";
295 ReadoutPacketPointerCache[block_num].push_back(ptr);
298 while (ReadoutPacketPointerCache[block_num].size() < hit_num + 1)
300 auto last_ptr = ReadoutPacketPointerCache[block_num].back();
301 auto ptr =
reinterpret_cast<const CalorimeterHitReadoutPacket *
>(
reinterpret_cast<const uint16_t *
>(last_ptr + 1) + last_ptr->NumberOfSamples);
302 if (reinterpret_cast<const uint8_t *>(ptr) > end_ptr)
304 TLOG(TLVL_ERROR) <<
"Fell off the end of the DataBlock while processing CalorimeterHitReadoutPackets!";
307 ReadoutPacketPointerCache[block_num].push_back(ptr);
309 return ReadoutPacketPointerCache[block_num][hit_num + 1];
312 const uint16_t *GetCalorimeterReadoutSample(
size_t block_num,
size_t hit_num,
size_t sample_num)
314 auto pkt = GetCalorimeterReadoutPacket(block_num, hit_num);
315 if (pkt ==
nullptr)
return nullptr;
316 if (sample_num >= pkt->NumberOfSamples)
318 TLOG(TLVL_ERROR) <<
"Requested sample index " << sample_num <<
" is greater than the maximum allowed (" << (pkt->NumberOfSamples - 1) <<
")!";
321 return reinterpret_cast<const uint16_t *
>(pkt + 1) + sample_num;
324 const CRVROCStatusPacket *GetCRVROCStatusPacket(
size_t block_num)
326 auto hdr = GetHeader(block_num);
327 if (hdr ==
nullptr)
return nullptr;
328 if (hdr->SubsystemID != 2)
330 TLOG(TLVL_ERROR) <<
"Trying to get CRV data packet from non-CRV DataBlock!";
334 if (blockSizeBytes(block_num) <
sizeof(DataBlockHeader) +
sizeof(CRVROCStatusPacket))
336 TLOG(TLVL_ERROR) <<
"Data Block size indicates that CRV ROC Status Packet is not present! This event is probably corrupt!";
340 auto crv_hdr =
reinterpret_cast<const CRVROCStatusPacket *
>(hdr + 1);
341 if (blockSizeBytes(block_num) <
sizeof(DataBlockHeader) + crv_hdr->ControllerEventWordCount)
343 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!";
350 size_t GetCRVHitCount(
size_t block_num)
352 auto hdr = GetCRVROCStatusPacket(block_num);
353 if (hdr ==
nullptr)
return 0;
355 size_t hit_bytes = hdr->ControllerEventWordCount -
sizeof(CRVROCStatusPacket);
357 size_t packet_count = hit_bytes /
sizeof(CRVHitReadoutPacket);
359 auto hit_packet =
reinterpret_cast<const CRVHitReadoutPacket *
>(hdr + 1);
360 if (*reinterpret_cast<const uint8_t *>(hit_packet + (packet_count - 1)) == 0)
368 const CRVHitReadoutPacket *GetCRVHitReadoutPacket(
size_t block_num,
size_t hit_idx)
370 auto hdr = GetCRVROCStatusPacket(block_num);
371 if (hdr ==
nullptr)
return nullptr;
373 auto hit_count = GetCRVHitCount(block_num);
374 if (hit_idx >= hit_count) {
375 TLOG(TLVL_ERROR) <<
"Requested hit index " << hit_idx <<
" is greater than the last hit index in this DataBlock (" << (hit_count - 1) <<
")!";
379 return reinterpret_cast<const CRVHitReadoutPacket *
>(hdr + 1) + hit_idx;
383 std::unordered_map<size_t, std::deque<const CalorimeterHitReadoutPacket *>> ReadoutPacketPointerCache;