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