Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
oncsSub_idtpcfeev3.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file oncsSub_idtpcfeev3.cc
1 #include "oncsSub_idtpcfeev3.h"
2 
3 #include <string.h>
4 #include <stdint.h>
5 
6 #define coutfl cout << __FILE__<< " " << __LINE__ << " "
7 #define cerrfl cerr << __FILE__<< " " << __LINE__ << " "
8 
9 using namespace std;
10 
12  :oncsSubevent_w2 (data)
13 {
14 
15  _is_decoded = 0;
16  _last_requested_element = -1; // impossible value to mark "unnused"
18 }
19 
20 
22 {
23 
24  for (auto itr = waveforms.begin() ; itr != waveforms.end() ; ++itr)
25  {
26  delete (*itr);
27  }
28  waveforms.clear();
29 
30  for (auto itr = waveform_vector.begin() ; itr != waveform_vector.end() ; ++itr)
31  {
32  delete (*itr);
33  }
34  waveform_vector.clear();
35 
36 
37  for (auto itr = gtm_data.begin() ; itr != gtm_data.end() ; ++itr)
38  {
39  delete (*itr);
40  }
41  gtm_data.clear();
42 
43 }
44 
46 {
47  if ( n < 0) return 0; // not ok
48  if ( _last_requested_element == n) return 1; // say "ok"
49 
50  unsigned i = n;
51  if ( i >= waveform_vector.size() )
52  {
55  return 0;
56  }
57 
60 
61  return 1;
62 }
63 
64 int oncsSub_idtpcfeev3::decode_gtm_data(unsigned short dat[16])
65 {
66  unsigned char *gtm = (unsigned char *)dat;
67  gtm_payload *payload = new gtm_payload;
68 
69  payload->pkt_type = gtm[0] | ((unsigned short)gtm[1] << 8);
70  if (payload->pkt_type != GTM_LVL1_ACCEPT_MAGIC_KEY && payload->pkt_type != GTM_ENDAT_MAGIC_KEY)
71  {
72  delete payload;
73  return -1;
74  }
75 
76  payload->is_lvl1 = payload->pkt_type == GTM_LVL1_ACCEPT_MAGIC_KEY;
77  payload->is_endat = payload->pkt_type == GTM_ENDAT_MAGIC_KEY;
78 
79  payload->bco = ((unsigned long long)gtm[2] << 0)
80  | ((unsigned long long)gtm[3] << 8)
81  | ((unsigned long long)gtm[4] << 16)
82  | ((unsigned long long)gtm[5] << 24)
83  | ((unsigned long long)gtm[6] << 32)
84  | (((unsigned long long)gtm[7]) << 40);
85  payload->lvl1_count = ((unsigned int)gtm[8] << 0)
86  | ((unsigned int)gtm[9] << 8)
87  | ((unsigned int)gtm[10] << 16)
88  | ((unsigned int)gtm[11] << 24);
89  payload->endat_count = ((unsigned int)gtm[12] << 0)
90  | ((unsigned int)gtm[13] << 8)
91  | ((unsigned int)gtm[14] << 16)
92  | ((unsigned int)gtm[15] << 24);
93  payload->last_bco = ((unsigned long long)gtm[16] << 0)
94  | ((unsigned long long)gtm[17] << 8)
95  | ((unsigned long long)gtm[18] << 16)
96  | ((unsigned long long)gtm[19] << 24)
97  | ((unsigned long long)gtm[20] << 32)
98  | (((unsigned long long)gtm[21]) << 40);
99  payload->modebits = gtm[22];
100 
101  this->gtm_data.push_back(payload);
102 
103  return 0;
104 }
105 
107 {
108 
109  if (_is_decoded ) return 0;
110  _is_decoded = 1;
111 
112  unsigned int payload_length = 2 * (getLength() - SEVTHEADERLENGTH - getPadding() );
113 
114  unsigned int index = 0;
115 
116 
117  unsigned short *buffer = ( unsigned short *) &SubeventHdr->data;
118 
119  // demultiplexer
120  while (index < payload_length)
121  {
122  // Length for the 256-bit wide Round Robin Multiplexer for the data stream
123  const unsigned int datalength = 0xf;
124 
125  if ((buffer[index] & 0xFF00) == FEE_MAGIC_KEY)
126  {
127 
128  unsigned int fee_id = buffer[index] & 0xff;
129  // coutfl << " index = " << index << " fee_id = " << fee_id << " len = " << datalength << endl;
130  ++index;
131  if (fee_id < MAX_FEECOUNT)
132  {
133  for (unsigned int i = 0; i < datalength; i++)
134  {
135  // watch out for any data corruption
136  if (index >= payload_length) break;
137 
138  fee_data[fee_id].push_back(buffer[index++]);
139  }
140  }
141  } else if ((buffer[index] & 0xFF00) == GTM_MAGIC_KEY) {
142  unsigned short buf[16];
143 
144  // memcpy?
145  for (unsigned int i = 0; i < 16; i++) {
146  buf[i] = buffer[index++];
147  }
148 
149  decode_gtm_data(buf);
150  }
151  else
152  {
153  // not FEE data, e.g. GTM data or other stream, to be decoded
154  index += datalength + 1;
155  }
156 
157  }
158  // coutfl << " done with tcp_decode index = " << index << endl;
159 
160  // std::vector<unsigned short>::const_iterator fee_data_itr;
161 
162  // for ( int ifee = 0 ; ifee < MAX_FEECOUNT ; ifee++)
163  // {
164 
165  // coutfl << " starting with fee number " << ifee << " size of vector " << fee_data[ifee].size() << endl;
166  // }
167 
168  for ( int ifee = 0 ; ifee < MAX_FEECOUNT ; ifee++)
169  {
170 
171  unsigned int pos; // I'm too tired to play with iterators; pos is the position in a FEE vector
172 
173  //for ( fee_data_itr = fee_data[ifee].begin(); fee_data_itr != fee_data[ifee].end(); )
174  for ( pos = 0; pos < fee_data[ifee].size() ; )
175  {
176  // itr = fee_data_itr;
177  int skip_amount = find_header (pos, fee_data[ifee]);
178  if ( skip_amount < 0) break;
179  //for ( int i = 0; i < skip_amount; i++) ++fee_data_itr; // skip that many words
180  pos += skip_amount;
181 
182  // as we advance pos, let's remember where the start is
183  unsigned int startpos = pos;
184 
185  // first the check if our vector cuts off before the fixed-length header, then we are already done
186  if ( startpos + HEADER_LENGTH >= fee_data[ifee].size() || startpos + fee_data[ifee][startpos] > fee_data[ifee].size())
187  {
188  pos = fee_data[ifee].size() + 1; // make sure we really terminate the loop
189  }
190  else
191  {
192  // capture the header so we can easier get the bit shift stuff
193  unsigned short header[HEADER_LENGTH];
194  for ( int i = 0; i < HEADER_LENGTH; i++ ) header[i] = (fee_data[ifee][pos++]) ;
195 
196  sampa_waveform *sw = new sampa_waveform;
197 
198  sw->fee = ifee;
199  sw->pkt_length = header[0];
200  sw->adc_length = header[5];
201  sw->sampa_address = (header[1] >> 5) & 0xf;
202  sw->sampa_channel = header[1] & 0x1f;
203  sw->channel = header[1] & 0x1ff;
204  sw->bx_timestamp = ((header[3] & 0x1ff) << 11)
205  | ((header[2] & 0x3ff) << 1)
206  | (header[1] >> 9);
207 
208  // now we add the actual waveform
209  unsigned short data_size = header[5] -1 ;
210 
211  // coutfl << " Fee: " << ifee << " Sampa " << sw->sampa_address
212  // << " sampa channel: " << sw->sampa_channel
213  // << " channel: " << sw->channel
214  // << " waveform length: " << data_size << endl;
215 
216  for (int i = 0 ; i < data_size ; i++)
217  {
218  sw->waveform.push_back( fee_data[ifee][pos++]);
219  }
220 
221  // we calculate the checksum here because "pos" is at the right place
222  unsigned short crc = crc16(ifee, startpos, header[0]-1);
223  // coutfl << "fee " << setw(3) << sw->fee
224  // << " sampla channel " << setw(3) << sw->channel
225  // << " crc and value " << hex << setw(5) << crc << " " << setw(5) << fee_data[ifee][pos] << dec;
226  // if ( crc != fee_data[ifee][pos] ) cout << " *********";
227  // cout << endl;
228 
229  sw->checksum = crc;
230  sw->valid = ( crc == fee_data[ifee][pos]);
231 
232  waveforms.insert(sw);
233  }
234 
235  //coutfl << "inserting at " << ifee*MAX_CHANNELS + sw->channel << " size is " << waveforms.size() << endl;
236  //waveform_vector[ifee*MAX_CHANNELS + sw->channel].push_back(sw);
237  }
238  }
239 
240  auto it = waveforms.begin();
241  for ( ; it != waveforms.end(); ++it)
242  {
243  waveform_vector.push_back( *it);
244  }
245  waveforms.clear();
246 
247  return 0;
248 }
249 
250 long long oncsSub_idtpcfeev3::lValue(const int n, const char *what)
251 {
252  tpc_decode();
253 
254  const size_t i = n;
255 
256  if (strcmp(what, "N_TAGGER") == 0) // the number of datasets
257  {
258  return gtm_data.size();
259  }
260 
261  else if (strcmp(what, "TAGGER_TYPE") == 0 )
262  {
263  if (i < gtm_data.size())
264  {
265  return gtm_data[i]->pkt_type;
266  }
267  }
268 
269  else if (strcmp(what, "IS_ENDAT") == 0 )
270  {
271  if (i < gtm_data.size())
272  {
273  return gtm_data[i]->is_endat;
274  }
275  }
276 
277  else if (strcmp(what, "IS_LEVEL1_TRIGGER") == 0 )
278  {
279  if (i < gtm_data.size())
280  {
281  return gtm_data[i]->is_lvl1;
282  }
283  }
284 
285  else if (strcmp(what, "BCO") == 0 )
286  {
287  if (i < gtm_data.size())
288  {
289  return gtm_data[i]->bco;
290  }
291  }
292 
293  else if (strcmp(what, "LEVEL1_COUNT") == 0 )
294  {
295  if (i < gtm_data.size())
296  {
297  return gtm_data[i]->lvl1_count;
298  }
299  }
300 
301  else if (strcmp(what, "ENDAT_COUNT") == 0 )
302  {
303  if (i < gtm_data.size())
304  {
305  return gtm_data[i]->endat_count;
306  }
307  }
308 
309  else if (strcmp(what, "LAST_BCO") == 0 )
310  {
311  if (i < gtm_data.size())
312  {
313  return gtm_data[i]->last_bco;
314  }
315  }
316 
317  else if (strcmp(what, "MODEBITS") == 0 )
318  {
319  if (i < gtm_data.size())
320  {
321  return gtm_data[i]->modebits;
322  }
323  }
324 
325  return 0;
326 }
327 
328 int oncsSub_idtpcfeev3::iValue(const int n, const int sample)
329 {
330  if ( n < 0) return 0;
331 
332  tpc_decode();
333 
334  if ( cacheIterator(n) )
335  {
336  unsigned int m = sample;
337  if ( m >= (_last_requested_waveform)->waveform.size() ) return 0;
338  return (_last_requested_waveform)->waveform[m];
339  }
340  return 0;
341 }
342 
343 
344 
345 
346 
347 int oncsSub_idtpcfeev3::iValue(const int n, const char *what)
348 {
349 
350  tpc_decode();
351 
352  if ( strcmp(what,"NR_WF") == 0 ) // the number of datasets
353  {
354  return waveform_vector.size();
355  }
356 
357  else if ( strcmp(what,"MAX_FEECOUNT") == 0 )
358  {
359  return MAX_FEECOUNT;
360  }
361 
362  // see how many samples we have
363  else if ( strcmp(what,"SAMPLES") == 0 )
364  {
365  if ( cacheIterator(n) )
366  {
367  return (int) (_last_requested_waveform)->waveform.size();
368  }
369  return 0;
370  }
371 
372  else if ( strcmp(what,"FEE") == 0 )
373  {
374  if ( cacheIterator(n) )
375  {
376  return (int) (_last_requested_waveform)->fee;
377  }
378  return 0;
379  }
380 
381  else if ( strcmp(what,"SAMPAADDRESS") == 0 )
382  {
383  if ( cacheIterator(n) )
384  {
385  return (int) (_last_requested_waveform)->sampa_address;
386  }
387  return 0;
388  }
389 
390  else if ( strcmp(what,"SAMPACHANNEL") == 0 )
391  {
392  if ( cacheIterator(n) )
393  {
394  return (int) (_last_requested_waveform)->sampa_channel;
395  }
396  return 0;
397  }
398 
399  else if ( strcmp(what,"CHANNEL") == 0 )
400  {
401  if ( cacheIterator(n) )
402  {
403  return (int) (_last_requested_waveform)->channel;
404  }
405  return 0;
406  }
407 
408  else if ( strcmp(what,"BCO") == 0 )
409  {
410  if ( cacheIterator(n) )
411  {
412  return (int) (_last_requested_waveform)->bx_timestamp;
413  }
414  return 0;
415  }
416 
417  else if ( strcmp(what,"CHECKSUM") == 0 )
418  {
419  if ( cacheIterator(n) )
420  {
421  return (int) (_last_requested_waveform)->checksum;
422  }
423  return 0;
424  }
425 
426  else if ( strcmp(what,"CHECKSUMERROR") == 0 )
427  {
428  if ( cacheIterator(n) )
429  {
430  if ( (_last_requested_waveform)->valid ) return 0;
431  return 1;
432  }
433  return 0;
434  }
435 
436  return 0;
437 
438 }
439 
440 //int oncsSub_idtpcfeev3::find_header ( std::vector<unsigned short>::const_iterator &itr, const std::vector<unsigned short> &orig)
441 int oncsSub_idtpcfeev3::find_header ( const unsigned int yy, const std::vector<unsigned short> &orig)
442 {
443  bool found = false;
444  unsigned int pos = yy;
445  std::vector<unsigned short> header_candidate;
446 
447  // we slide over the data and find the header, if any.
448  // we calculate and return the amount of words we need to skip to find the vector.
449  // if we find it right away, the amount returned is 0;
450  // -1 for an error condition or end, like we hit the end without finding another header.
451  // the complication here is that we look ahead a few words to recognize it.
452 
453  for ( unsigned int i = 0; i < HEADER_LENGTH ; i++) // we start out with one "header candidate" = 7 entries
454  {
455  if ( pos >= orig.size()) // if we reached the end, no more header here
456  {
457  return -1;
458  }
459 
460  header_candidate.push_back(orig[pos]);
461  pos++;
462  }
463 
464  int skip_amount = 0;
465  while ( ! found)
466  {
467  // coutfl << " current pos is " << pos << " vector length " << orig.size() << endl;
468 
469  if (header_candidate[4] == MAGIC_KEY_0 && header_candidate[6] == MAGIC_KEY_1 && (header_candidate[0] - header_candidate[5] == HEADER_LENGTH))
470  {
471  // found it!
472  found = true;
473  // coutfl << " found header skip value = " << skip_amount << endl;
474  break;
475  }
476  skip_amount++;
477  if ( pos >= orig.size()) // if we reached the end, no more header here
478  {
479  return -1;
480  }
481 
482  // coutfl << " next value " << pos << " " << hex << orig[pos] << dec << endl;
483  header_candidate.erase(header_candidate.begin()); // delete the vector 1st element
484  header_candidate.push_back(orig[pos]); // push a new value, rinse and repeat
485  pos++;
486  }
487 
488  return skip_amount;
489 }
490 
492 {
493  tpc_decode();
494  identify(os);
495 
496  if (lValue(0, "N_TAGGER") == 0)
497  os << " No lvl1 and Endat taggers" << endl;
498  else
499  {
500  os << " TAGGER_TYPE BCO LEVEL1 CNT ENDAT CNT LAST_BCO MODEBITS" << endl;
501 
502  for (int i = 0; i < lValue(0, "N_TAGGER"); ++i) // go through the datasets
503  {
504  os << " 0x" << setw(4) << hex << lValue(i, "TAGGER_TYPE") << dec
505  << " (" << (lValue(i, "IS_ENDAT") ? "ENDAT" : "") << (lValue(i, "IS_LEVEL1_TRIGGER") ? "LVL1 " : "")
506  << ") "
507  << setw(12) << hex << lValue(i, "BCO") << dec << " "
508  << setw(10) << lValue(i, "LEVEL1_COUNT") << " "
509  << setw(10) << lValue(i, "ENDAT_COUNT") << " "
510  << setw(12) << hex << lValue(i, "LAST_BCO") << dec
511  << " 0x" << std::setfill('0') << setw(2) << hex << lValue(i, "MODEBITS") << std::setfill(' ')<< dec
512  << endl;
513  }
514 
515  os << endl;
516  }
517 
518  os << " number of waveforms " << iValue(0, "NR_WF") << endl;
519 
520  for ( int i = 0; i < iValue(0, "NR_WF") ; i++) // go through the datasets
521  {
522  os << " FEE Channel Sampachannel Samples BCO CRC_ERR" << endl;
523 
524  os << setw(5) << iValue(i, "FEE") << " "
525  << setw(9) << iValue(i, "CHANNEL") << " "
526  << setw(9) << iValue(i, "SAMPACHANNEL") << " "
527  << setw(12) << iValue(i, "SAMPLES") << " "
528  << " 0x" << setw(5) << hex << iValue(i, "BCO") << dec
529  // << " 0x" << setw(4) << hex << iValue(i, "CHECKSUM") << dec
530  << setw(4) << iValue(i, "CHECKSUMERROR")
531  << endl;
532 
533  for (int j = 0; j < iValue(i, "SAMPLES") ; j += 10)
534  {
535  os << " ";
536  for (int k = 0; k < 10 ; k++)
537  {
538  os << setw(4) << iValue(i,j+k) << " ";
539  }
540  os << endl;
541  }
542  os << endl;
543 
544  }
545 }
546 
547 
548 
549 unsigned short oncsSub_idtpcfeev3::reverseBits(const unsigned short x) const
550 {
551  unsigned short n = x;
552  n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
553  n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
554  n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
555  n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
556  //n = (n >> 16) & 0x0000ffff | (n << 16) & 0xffff0000;
557  return n;
558 }
559 
560 
561 
562 unsigned short oncsSub_idtpcfeev3::crc16(const unsigned int fee, const unsigned int index, const int l) const
563 {
564 
565  unsigned short crc = 0xffff;
566 
567  for ( int i = 0; i < l; i++)
568  {
569  unsigned short x = fee_data[fee][index+i];
570  // cout << "in crc " << hex << x << dec << endl;
571  crc ^= reverseBits( x);
572  for (unsigned short k = 0; k < 16; k++)
573  {
574  crc = crc & 1 ? (crc >> 1) ^ 0xa001 : crc >> 1;
575  }
576  }
577  crc = reverseBits(crc);
578  return crc;
579 }
580