mu2e_artdaq_core  v1_02_25
 All Classes Functions
mu2eFragmentReader.hh
1 #ifndef mu2e_artdaq_core_Overlays_mu2eFragmentReader_hh
2 #define mu2e_artdaq_core_Overlays_mu2eFragmentReader_hh
3 
5 // mu2eFragmentReader
6 //
7 // Class derived from mu2eFragment which provides additional methods
8 // for accessing data stored in a mu2eFragment
9 //
11 
12 #include "artdaq-core/Data/Fragment.hh"
13 #include "artdaq-core/Data/Fragments.hh"
14 #include "mu2e-artdaq-core/Overlays/mu2eFragment.hh"
15 
16 #include <bitset>
17 
18 #include <iostream>
19 
20 namespace mu2e {
21 class mu2eFragmentReader;
22 }
23 
25 {
26 public:
27  typedef uint16_t adc_t;
28 
29  mu2eFragmentReader(artdaq::Fragment const &f)
30  : mu2eFragment(f){};
31 
32  size_t blockIndexBytes(size_t offset) const;
33 
34  size_t blockSizeBytes() const;
35  size_t blockSizeBytes(size_t offset) const;
36  size_t blockEndBytes(size_t offset) const;
37  Header::data_t const *dataAtBytes(size_t offset) const;
38  Header::data_t const *dataAtBlockIndex(size_t offset) const;
39 
40  void printPacketAtByte(size_t offset) const;
41 
42  // DataBlock Header Accessor Methods (by block address)
43  adc_t DBH_ByteCount(adc_t const *pos);
44  bool DBH_Valid(adc_t const *pos);
45  adc_t DBH_ROCID(adc_t const *pos);
46  adc_t DBH_PacketType(adc_t const *pos);
47  adc_t DBH_PacketCount(adc_t const *pos);
48  uint64_t DBH_Timestamp(adc_t const *pos);
49  adc_t DBH_TimestampLow(adc_t const *pos);
50  adc_t DBH_TimestampMedium(adc_t const *pos);
51  adc_t DBH_TimestampHigh(adc_t const *pos);
52  adc_t DBH_Status(adc_t const *pos);
53  adc_t DBH_FormatVersion(adc_t const *pos);
54  adc_t DBH_EVBMode(adc_t const *pos);
55  adc_t DBH_SubsystemID(adc_t const *pos);
56  adc_t DBH_DTCID(adc_t const *pos);
57 
58  // TRK DataBlock Payload Accessor Methods (by block address)
59  adc_t DBT_StrawIndex(adc_t const *pos);
60  uint32_t DBT_TDC0(adc_t const *pos);
61  uint32_t DBT_TDC1(adc_t const *pos);
62  uint32_t DBT_TOT0(adc_t const *pos);
63  uint32_t DBT_TOT1(adc_t const *pos);
64  std::array<adc_t, 15> DBT_Waveform(adc_t const *pos);
65  adc_t DBT_Flags(adc_t const *pos);
66 
67  // CAL DataBlock Payload Accessor Methods (by block address)
68  adc_t DBC_CrystalID(adc_t const *pos);
69  adc_t DBC_apdID(adc_t const *pos);
70  adc_t DBC_Time(adc_t const *pos);
71  adc_t DBC_NumSamples(adc_t const *pos);
72  adc_t DBC_PeakSampleIdx(adc_t const *pos);
73  std::vector<adc_t> DBC_Waveform(adc_t const *pos);
74 
75 protected:
76  // Bit processing helper methods
77  // For now, the focus is on clarity and ease of use, but eventually
78  // these sorts of functions will need to be optimized for efficiency
79 
80  // bitArray populates a 128-bit bitset using the 128 bits beginning
81  // at the position indicated by the provided pointer
82  // std::bitset<128> bitArray(adc_t const * beginning);
83  std::bitset<128> bitArray(adc_t const *beginning) const;
84 
85  // Populates the provided bitset using the 128 bits beginning at the
86  // position indicated by the provided pointer
87  void fillBitArray(std::bitset<128> &theArray, adc_t const *beginning);
88 
89  void printBitArray(std::bitset<128> theArray);
90 
91  // Accepts a 128 bit bitset and converts the bits from minIdx to maxIdx
92  // into a 16-bit adc_t (minIdx and maxIdx should be within 16 bits of
93  // each other as no error-checking is performed at the moment).
94  adc_t convertFromBinary(std::bitset<128> theArray, int minIdx, int maxIdx) const;
95 };
96 
97 // Convert index in number of DataBlocks to index in bytes
98 inline size_t mu2e::mu2eFragmentReader::blockIndexBytes(size_t offset) const
99 {
100  if (hdr_block_count() == 0) {
101  return 0;
102  }
103  else if (offset >= hdr_block_count())
104  {
105  return -1;
106  }
107  else if (offset == 0)
108  {
109  return 0;
110  }
111  return header_()->index[offset - 1];
112 }
113 
114 // Return size of all blocks
115 inline size_t mu2e::mu2eFragmentReader::blockSizeBytes() const { return mu2eFragment::dataEndBytes(); }
116 
117 // Return size of block at given DataBlock index
118 inline size_t mu2e::mu2eFragmentReader::blockSizeBytes(size_t offset) const
119 {
120  if (hdr_block_count() == 0) {
121  return 0;
122  }
123  else if (offset > hdr_block_count() - 1)
124  {
125  return 0;
126  }
127  else if (offset == 0)
128  {
129  return header_()->index[offset];
130  }
131  return header_()->index[offset] - header_()->index[offset - 1];
132 }
133 
134 // Return size of block at given DataBlock index
135 inline size_t mu2e::mu2eFragmentReader::blockEndBytes(size_t offset) const
136 {
137  if (hdr_block_count() == 0) {
138  return 0;
139  }
140  else if (offset > hdr_block_count() - 1)
141  {
142  return 0;
143  }
144  return header_()->index[offset];
145 }
146 
147 // Return pointer to beginning of DataBlock at given byte index
148 inline mu2e::mu2eFragmentReader::Header::data_t const *mu2e::mu2eFragmentReader::dataAtBytes(size_t offset) const
149 {
150  return dataBegin() + (offset / sizeof(Header::data_t));
151 }
152 
153 // Return pointer to beginning of DataBlock at given DataBlock index
154 inline mu2e::mu2eFragmentReader::Header::data_t const *mu2e::mu2eFragmentReader::dataAtBlockIndex(size_t offset) const
155 {
156  return dataAtBytes(blockIndexBytes(offset));
157 }
158 
159 void mu2e::mu2eFragmentReader::printPacketAtByte(size_t offset) const
160 {
161  std::bitset<128> theArray = bitArray(reinterpret_cast<mu2e::mu2eFragmentReader::adc_t const *>(dataAtBytes(offset)));
162  std::cout << "\t\t"
163  << "Packet Bits (128): ";
164  for (int i = 0; i < 128; i++) {
165  std::cout << theArray[i];
166  if (i != 0 && i < 128 - 1 && (i + 1) % 8 == 0) {
167  std::cout << " ";
168  }
169  }
170  std::cout << std::endl;
171  return;
172 }
173 
174 std::bitset<128> mu2e::mu2eFragmentReader::bitArray(mu2e::mu2eFragmentReader::adc_t const *beginning) const
175 {
176  // Return 128 bit bitset filled with bits starting at the indicated position in the fragment
177  std::bitset<128> theArray;
178  for (int bitIdx = 127, adcIdx = 0; adcIdx < 8; adcIdx++) {
179  for (int offset = 0; offset < 16; offset++) {
180  if (((*((adc_t const *)(beginning + adcIdx))) & (1 << offset)) != 0) {
181  theArray.set(bitIdx);
182  }
183  else
184  {
185  theArray.reset(bitIdx);
186  }
187  bitIdx--;
188  }
189  }
190  return theArray;
191 }
192 
193 void mu2e::mu2eFragmentReader::fillBitArray(std::bitset<128> &theArray,
194  mu2e::mu2eFragmentReader::adc_t const *beginning)
195 {
196  // Fill bitset using the 128 bits starting at the indicated position in the fragment
197  for (int bitIdx = 127, adcIdx = 0; adcIdx < 8; adcIdx++) {
198  for (int offset = 0; offset < 16; offset++) {
199  if (((*((adc_t const *)(beginning + adcIdx))) & (1 << offset)) != 0) {
200  theArray.set(bitIdx);
201  }
202  else
203  {
204  theArray.reset(bitIdx);
205  }
206  bitIdx--;
207  }
208  }
209 }
210 
211 void mu2e::mu2eFragmentReader::printBitArray(std::bitset<128> theArray)
212 {
213  // Print all 128 bits in the packet
214  std::cout << "\t\t"
215  << "Packet Bits (128): ";
216  for (int i = 0; i < 128; i++) {
217  std::cout << theArray[i];
218  }
219  std::cout << std::endl;
220 }
221 
222 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::convertFromBinary(std::bitset<128> theArray, int minIdx,
223  int maxIdx) const
224 {
225  std::bitset<16> retVal;
226  for (int i = minIdx + 1; i <= maxIdx; i++) {
227  retVal.set(maxIdx - i, theArray[i]);
228  }
229  return retVal.to_ulong();
230 }
231 
233 // DataBlock Header Accessor Methods (by block address)
235 
236 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBH_ByteCount(adc_t const *pos) { return *(pos + 0); }
237 
238 bool mu2e::mu2eFragmentReader::DBH_Valid(adc_t const *pos) { return (*(pos + 1) >> 15) & 0x0001; }
239 
240 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBH_ROCID(adc_t const *pos)
241 {
242  return *(pos + 1) & 0x000F; // 0x000F = 0b1111
243 }
244 
245 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBH_PacketType(adc_t const *pos)
246 {
247  return (*(pos + 1) >> 4) & 0x000F; // 0x000F = 0b1111
248 }
249 
250 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBH_PacketCount(adc_t const *pos)
251 {
252  return *(pos + 2) & 0x07FF; // 0x07FF = 0b0111 1111 1111
253 }
254 
255 uint64_t mu2e::mu2eFragmentReader::DBH_Timestamp(adc_t const *pos)
256 {
257  return uint64_t(*(pos + 3)) + (uint64_t(*(pos + 4)) << 16) + (uint64_t(*(pos + 5)) << 32);
258 }
259 
260 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBH_TimestampLow(adc_t const *pos) { return *(pos + 3); }
261 
262 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBH_TimestampMedium(adc_t const *pos) { return *(pos + 4); }
263 
264 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBH_TimestampHigh(adc_t const *pos) { return *(pos + 5); }
265 
266 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBH_Status(adc_t const *pos)
267 {
268  return *(pos + 6) & 0x00FF; // 0x00FF = 0b1111 1111
269 }
270 
271 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBH_FormatVersion(adc_t const *pos)
272 {
273  return *(pos + 6) >> 8;
274 }
275 
276 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBH_EVBMode(adc_t const *pos) { return *(pos + 7) >> 8; }
277 
278 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBH_SubsystemID(adc_t const *pos)
279 {
280  return (*(pos + 7) >> 6) & 0x0003; // 0x0003 = 0b0011
281 }
282 
283 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBH_DTCID(adc_t const *pos)
284 {
285  return *(pos + 7) & 0x003F; // 0x003F = 0b0011 1111
286 }
287 
289 // TRK DataBlock Payload Accessor Methods (by block address)
291 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBT_StrawIndex(adc_t const *pos) { return *(pos + 8 + 0); }
292 
293 uint32_t mu2e::mu2eFragmentReader::DBT_TDC0(adc_t const *pos) { return (uint32_t(*(pos + 8 + 1)) & 0xFFFF); }
294 
295 uint32_t mu2e::mu2eFragmentReader::DBT_TDC1(adc_t const *pos) { return (uint32_t(*(pos + 8 + 2)) & 0xFFFF); }
296 
297 uint32_t mu2e::mu2eFragmentReader::DBT_TOT0(adc_t const *pos) { return (uint32_t(*(pos + 8 + 3)) & 0x00FF); }
298 
299 uint32_t mu2e::mu2eFragmentReader::DBT_TOT1(adc_t const *pos) { return ((uint32_t(*(pos + 8 + 3)) >> 8) & 0x00FF); }
300 
301 std::array<mu2e::mu2eFragmentReader::adc_t, 15> mu2e::mu2eFragmentReader::DBT_Waveform(adc_t const *pos)
302 {
303  std::array<adc_t, 15> waveform;
304 
305  // Four 12-bit tracker ADC samples fit into every three slots (16 bits * 3)
306  // when we pack them tightly
307 
308  for (size_t i = 0; i < 4; i += 1) {
309  waveform[0 + i * 4] = *(pos + 8 + 4 + i * 3) & 0x0FFF;
310  waveform[1 + i * 4] = ((*(pos + 8 + 4 + i * 3 + 1) & 0x00FF) << 4) | (*(pos + 8 + 4 + i * 3) >> 12);
311  waveform[2 + i * 4] = ((*(pos + 8 + 4 + i * 3 + 2) & 0x000F) << 8) | (*(pos + 8 + 4 + i * 3 + 1) >> 8);
312  if (i < 3) {
313  waveform[3 + i * 4] = (*(pos + 8 + 4 + i * 3 + 2) >> 4);
314  }
315  }
316 
317  return waveform;
318 }
319 
320 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBT_Flags(adc_t const *pos) { return (*(pos + 8 + 15) >> 8); }
321 
323 // CAL DataBlock Payload Accessor Methods (by block address)
325 
326 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBC_CrystalID(adc_t const *pos)
327 {
328  return *(pos + 8 + 0) & 0x0FFF; // 0x0FFF = 0b1111 1111 1111
329 }
330 
331 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBC_apdID(adc_t const *pos) { return *(pos + 8 + 0) >> 12; }
332 
333 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBC_Time(adc_t const *pos) { return *(pos + 8 + 1); }
334 
335 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBC_NumSamples(adc_t const *pos)
336 {
337  return *(pos + 8 + 2) & 0x00FF;
338 }
339 
340 mu2e::mu2eFragmentReader::adc_t mu2e::mu2eFragmentReader::DBC_PeakSampleIdx(adc_t const *pos)
341 {
342  return *(pos + 8 + 2) >> 8;
343 }
344 
345 std::vector<mu2e::mu2eFragmentReader::adc_t> mu2e::mu2eFragmentReader::DBC_Waveform(adc_t const *pos)
346 {
347  std::vector<int> waveform(DBC_NumSamples(pos));
348  for (size_t i = 0; i < waveform.size(); i++) {
349  waveform[i] = *(pos + 8 + 3 + i);
350  }
351  return waveform;
352 }
353 
354 #endif /* mu2e_artdaq_Overlays_mu2eFragmentReader_hh */