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