EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
oncsSub_idmvtxv0.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file oncsSub_idmvtxv0.cc
1 #include "oncsSub_idmvtxv0.h"
2 #include <cstring>
3 #include <bitset>
4 #include <map>
5 #include <vector>
6 
7 #include <arpa/inet.h>
8 
9 using namespace std;
10 
12  :oncsSubevent_w4 (data)
13 {
14  _is_decoded = 0;
16  _bad_ruid = 0;
17  _bad_ruchns = 0;
18  _bad_chipids = 0;
20  _highest_chip = -1;
21  memset ( chip_row, 0, 9*512*32*sizeof(unsigned int));
22  memset ( chip_rowmap, 0, 9*512*sizeof(unsigned int));
23  for ( int i = 0; i < MAXRUCHN+1; i++)
24  {
25  _chip_id[i] = -1;
26  _highest_region[i] = -1;
27  _unexpected_bytes[i] = 0;
28  _bunchcounter[i] = -1;
29  _header_found[i] = false;
30  _trailer_found[i] = false;
31  _readout_flags[i] = -1;
32  }
34 }
35 
37 {
38 
39 }
40 
41 
42 typedef struct
43 {
44  unsigned char d0[3][10];
45  unsigned char counter;
46  unsigned char ruid;
47 } data32;
48 
49 #define CHIPHEADER 1
50 #define CHIPEMPTYFRAME 2
51 #define DATASHORT 3
52 #define DATALONG0 4
53 #define DATALONG1 5
54 
55 int oncsSub_idmvtxv0::decode_thebit(int the_row, int encoder_id, int address) const
56 {
57  // the numbering "snakes" its way through a column (fig. 4.5 in the Alpide manual)
58  // 0 1 > > row 0
59  // 3 2 < < row 1
60  // 4 5 > > row 2
61  // 7 6 < < so we need to know if we are in an even or odd row
62  int is_an_odd_row = the_row & 1;
63  int thebit;
64  if ( is_an_odd_row)
65  {
66  thebit = (encoder_id*2) + ( ( address &1) ^ 1 );
67  }
68  else
69  {
70  thebit = (encoder_id*2) + ( address&1);
71  }
72  return thebit;
73 }
74 
75 void oncsSub_idmvtxv0::print_stuff(OSTREAM& out, unsigned int data, int width, int shift, bool blank) const
76 {
77  unsigned int mask = 0xffffffff;
78  if (width<8) mask = ((1 << width*4)-1);
79  if (blank)
80  for (int i=0;i<width;i++) out << " ";
81  else
82  out << std::hex << SETW(width) << std::setfill('0') << ((data>>shift) & mask);
83 }
84 
86 {
87  if ( _is_decoded) return 0;
88  _is_decoded = 1;
89 
90  unsigned int *payload = (unsigned int *) &SubeventHdr->data; // here begins the payload
91 
92  int dlength = getLength()-4 - getPadding(); //padding is supposed to be in units of dwords, this assumes dwords
93  unsigned char *the_end = ( unsigned char *) &payload[dlength+1];
94 
95  unsigned char *pos = (unsigned char *) payload;
96 
97  // cout << hex << " pos = " << (unsigned long long ) pos << " the end " << (unsigned long long) the_end << dec << endl;
98 
99  //pos = (unsigned char *) payload;
100 
101  unsigned char b;
102 
103  vector<unsigned char> ruchn_stream[MAXRUCHN+1];
104 
105  unsigned char felix_counter = 0;
106 
107  while ( pos < the_end )
108  {
109 
110  data32 *d32 = ( data32*) pos;
111 
112  if (d32->ruid > MAXRUID)
113  {
114  //cout << __FILE__ << " " << __LINE__ << " --- invalid ruid " << hex << (int) d32->ruid << " at pos " << (long) pos << dec << endl;
115  _bad_ruid = d32->ruid;
116  break;
117  }
118  //FELIX counter is 8 bits, max value 256
119  //check that the new counter value is consistent with the previous value (it should have increased by no more than 3, and the amount of the difference is the number of data chunks in this FELIX word)
120  int counter_increment = (d32->counter + 256 - felix_counter)%256;
121  if (counter_increment > 3)
122  {
123  if (d32->counter != 0)
124  {
125  //cout << __FILE__ << " " << __LINE__ << " --- unexpected FELIX counter " << hex << (int) d32->counter << " following previous counter value " << felix_counter << " at pos " << (long) pos << dec << endl;
127  }
128  break;
129  }
130  felix_counter = d32->counter;
131 
132  //for (int ichnk = 0; ichnk < 3; ichnk++)
133  for (int ichnk = 0; ichnk < counter_increment; ichnk++)
134  {
135  unsigned int ruchn = (unsigned int)d32->d0[ichnk][9];
136  if (ruchn == RUHEADER)
137  {
138  //cout << __FILE__ << " " << __LINE__ << " --- RU header " << hex << ruchn << ", full RU word: ";
139  //for (int ibyte=9;ibyte>=0;ibyte--)
140  //{
141  //cout << setfill('0') << setw(2) << hex << (unsigned int) d32->d0[ichnk][ibyte] << " ";
142  //}
143  //cout << setfill(' ') << setw(0) << dec << endl;
144  }
145  else if (ruchn == RUTRAILER)
146  {
147  //cout << __FILE__ << " " << __LINE__ << " --- RU trailer " << hex << ruchn << ", full RU word: ";
148  //for (int ibyte=9;ibyte>=0;ibyte--)
149  //{
150  //cout << setfill('0') << setw(2) << hex << (unsigned int) d32->d0[ichnk][ibyte] << " ";
151  //}
152  //cout << setfill(' ') << setw(0) << dec << endl;
153  }
154  else if (ruchn > MAXRUCHN)
155  {
156  _bad_ruchns++;
157  cout << __FILE__ << " " << __LINE__ << " --- invalid ruchn " << hex << ruchn << ", full RU word: ";
158  for (int ibyte=9;ibyte>=0;ibyte--)
159  {
160  cout << setfill('0') << setw(2) << hex << (unsigned int) d32->d0[ichnk][ibyte] << " ";
161  }
162  cout << setfill(' ') << setw(0) << dec << endl;
163  }
164  else for ( int ibyte = 0; ibyte < 9; ibyte++)
165  {
166  //cout << __FILE__ << " " << __LINE__ << hex << " --- ruchn " << ruchn << " byte " << (unsigned int) d32->d0[ichnk][ibyte] << dec << endl;
167  ruchn_stream[ruchn].push_back(d32->d0[ichnk][ibyte]);
168  }
169  } // ichnk
170 
171  pos += sizeof(*d32);
172  } // while (pos < the_end)
173 
174  //we ignore ruchn 0 (trigger information and padding words) for now
175  /*
176  if (ruchn_stream[0].size()!=9) for ( int ruchn = 0; ruchn < MAXRUCHN+1; ruchn++)
177  {
178  cout << __FILE__ << " " << __LINE__ << " --- ruchn " << ruchn << " has " << ruchn_stream[ruchn].size() << " bytes" << endl;
179  }
180  */
181 
182  for ( int ruchn = 1; ruchn < MAXRUCHN+1; ruchn++)
183  {
184 
185  bool header_seen=false;
186  int status = 0;
187  int ibyte_endofdata = -1;
188  int the_region = -1;
189  unsigned int address=0;
190  unsigned int encoder_id = 0;
191  for (unsigned int ibyte = 0; ibyte < ruchn_stream[ruchn].size(); ibyte++)
192  {
193  b = ruchn_stream[ruchn].at(ibyte);
194 
195  //cout << __FILE__ << " " << __LINE__ << " --- ruchn " << hex << ruchn << " next value " << (unsigned int) b << dec << " status:" << status << endl;
196 
197  if (status) // we mop up what we started in the last round -
198  // these are all cases with more than one byte
199  {
200  switch (status)
201  {
202  case CHIPHEADER:
203 
204  _bunchcounter[ruchn] = b;
205  //cout << __FILE__ << " " << __LINE__ << " chip header, ruchn= " << ruchn << " bunchctr= " << hex << _bunchcounter[ruchn] << dec << endl;
206  if ( (int)ruchn > _highest_chip)
207  {
208  _highest_chip = ruchn;
209  }
210  status = 0;
211  _header_found[ruchn] = true;
212  break;
213 
214  case CHIPEMPTYFRAME:
215 
216  _bunchcounter[ruchn] = b;
217  // cout << __FILE__ << " " << __LINE__ << " chip empty frame " << hex << ruchn << " " << _bunchcounter[ruchn] << dec << endl;
218  if ( (int)ruchn > _highest_chip)
219  {
220  _highest_chip = ruchn;
221  }
222  _highest_region[ruchn] = 0;
223  ibyte_endofdata = ibyte;
224  _header_found[ruchn] = true;
225  _trailer_found[ruchn] = true;
226  status = 0;
227  break;
228 
229  case DATASHORT:
230  address += b;
231  //cout << __FILE__ << " " << __LINE__ << " data short report, hex:" << hex << address << dec << " enc. id " << encoder_id << " address= " << address << " the_region:" << the_region << " ruchn:" << ruchn;
232  if ( the_region >= 0 && encoder_id >=0 )
233  {
234  int the_row = (address >> 1);
235  if ( the_row > 511)
236  {
237  cout << __FILE__ << " " << __LINE__ << " impossible row: " << the_row
238  << " encoder " << encoder_id << " addr " << address << endl;
239  }
240  else
241  {
242  int thebit = decode_thebit(the_row, encoder_id, address);
243  //cout << " row:" << the_row << " col:" << the_region*32 + thebit << endl;
244  // cout << __FILE__ << " " << __LINE__ << " the bit " << thebit << endl;
245  chip_row[ruchn][the_row][the_region] |= ( 1<<thebit);
246  chip_rowmap[ruchn][the_row] |= ( 1<<the_region);
247  if ( the_row > _highest_row_overall) _highest_row_overall = the_row;
248 
249  }
250  }
251 
252  //cout << endl;
253  status = 0;
254  break;
255 
256  case DATALONG0:
257  address += b;
258  status = DATALONG1;
259  break;
260 
261  case DATALONG1:
262  if ( (b & 0x80) != 0) //required to be 0
263  {
264  //cout << __FILE__ << " " << __LINE__ << " unexpected word " << hex << (unsigned int) b << dec << " at ibyte " << ibyte << endl;
265  _unexpected_bytes[ruchn]++;
266  }
267  //cout << __FILE__ << " " << __LINE__ << " data long report, hex:" << hex << address << dec << " enc. id " << encoder_id << " address= " << address << " the_region:" << the_region << " ruchn:" << ruchn << endl;
268  // Loop over the hits in the cluster. The pixel specified by the address always has a hit.
269  // The next 7 pixels (in priority encoder order) have hits if the corresponding bit in this byte is high.
270  // See ALPIDE manual section 3.4.1 on DATA LONG: page 63.
271  for (int ihit = 0; ihit<8; ihit++)
272  {
273  if (ihit==0 || ((b >> (ihit-1)) & 1))
274  {
275  int hit_address = address + ihit;
276  if ( the_region >= 0 && encoder_id >=0 )
277  {
278  int the_row = (hit_address >> 1);
279  if ( the_row > 511)
280  {
281  cout << __FILE__ << " " << __LINE__ << " impossible row: " << the_row
282  << " encoder " << encoder_id << " addr " << hit_address << endl;
283  }
284  else
285  {
286  int thebit = decode_thebit(the_row, encoder_id, hit_address);
287  //cout << " row:" << the_row << " col:" << the_region*32 + thebit << endl;
288  // cout << __FILE__ << " " << __LINE__ << " the bit " << thebit << endl;
289  chip_row[ruchn][the_row][the_region] |= ( 1<<thebit);
290  chip_rowmap[ruchn][the_row] |= ( 1<<the_region);
291  if ( the_row > _highest_row_overall) _highest_row_overall = the_row;
292 
293  }
294  }
295  }
296  }
297  status = 0;
298  break;
299 
300  }
301  continue;
302  }
303 
304  if (ibyte_endofdata != -1) break;
305 
306  if ( b == 0xff) // Idle byte, skip
307  {
308  //cout << __FILE__ << " " << __LINE__ << " IDLE byte " << hex << (unsigned int) b << dec << endl;
309  status = 0;
310  }
311 
312  else if ( ( b >> 4) == 0xa) // we have a chip header
313  {
314  _chip_id[ruchn] = ( b & 0xf);
315  header_seen = true;
316  status = CHIPHEADER;
317  }
318 
319  else if ( ( b >> 4) == 0xb) // we have a chip trailer
320  {
321  // cout << __FILE__ << " " << __LINE__ << " chip trailer, ruchn= " << hex << ruchn << dec << endl;
322  // break out of the loop, done with this chip
323  ibyte_endofdata = ibyte;
324  _trailer_found[ruchn] = true;
325  _readout_flags[ruchn] = (b & 0xf);
326  break;
327  }
328 
329  else if ( ( b >> 4) == 0xE) // we have a chip empty frame
330  {
331  _chip_id[ruchn] = ( b & 0xf);
332  header_seen = true;
333  status = CHIPEMPTYFRAME;
334  }
335 
336  else if ( ( b >> 5) == 0x6) // we have a region header
337  {
338  unsigned int region_id = (b & 0x1f);
339  if ( region_id <32)
340  {
341  the_region = region_id;
342  _highest_region[ruchn] = region_id;
343  }
344  else //this is impossible since the region ID is 5 bits
345  {
346  cout << __FILE__ << " " << __LINE__ << " wrong region header, id= " << hex << region_id << dec << endl;
347  }
348  }
349 
350  else if ( ( b >> 6) == 0x1) // we have a DATA short report
351  {
352  encoder_id = ( b>>2) & 0xf;
353  address = (b & 0x3) << 8;
354  status = DATASHORT;
355  }
356 
357  else if ( ( b >> 6) == 0x0) // we have a DATA long report
358  {
359  encoder_id = ( b>>2) & 0xf;
360  address = (b & 0x3) << 8;
361  status = DATALONG0;
362  }
363 
364  else if ( b == 0xF1) // we have a BUSY on
365  {
366  //cout << __FILE__ << " " << __LINE__ << " Busy on " << endl;
367  }
368 
369  else if ( b == 0xF0) // we have a BUSY off
370  {
371  //cout << __FILE__ << " " << __LINE__ << " Busy off " << endl;
372  }
373 
374  else
375  {
376  //cout << __FILE__ << " " << __LINE__ << " unexpected word " << hex << (unsigned int) b << dec << " at ibyte " << ibyte << endl;
377  _unexpected_bytes[ruchn]++;
378  }
379  if (ibyte==0 && !header_seen) break;//first byte of the ALPIDE stream must be a chip header or chip empty; if not, abort so we don't get confused by bad data
380 
381  } // ibyte
382 
383  //cout << __FILE__ << " " << __LINE__ << " ruchn " << ruchn << " ibyte_endofdata " << ibyte_endofdata << endl;
384  for (unsigned int ibyte = ibyte_endofdata+1; ibyte < ruchn_stream[ruchn].size(); ibyte++)
385  {
386  b = ruchn_stream[ruchn].at(ibyte);
387  if (b!=0)
388  {
389  //cout << __FILE__ << " " << __LINE__ << " --- ruchn " << hex << ruchn << " unexpected nonzero value " << (unsigned int) b << dec << " at ibyte " << ibyte << " after ibyte_endofdata " << ibyte_endofdata << endl;
391  }
392  }
393  } // ruchn
394 
395 
396  return 0;
397 }
398 
399 
400 int oncsSub_idmvtxv0::iValue(const int ich,const char *what)
401 {
402  mvtx_decode();
403  if ( strcmp(what,"UNEXPECTED_FELIX_COUNTER") == 0 )
404  {
406  }
407 
408  else if ( strcmp(what,"BAD_RUID") == 0 )
409  {
410  return _bad_ruid;
411  }
412 
413  else if ( strcmp(what,"BAD_RUCHNS") == 0 )
414  {
415  return _bad_ruchns;
416  }
417 
418  else if ( strcmp(what,"BAD_CHIPIDS") == 0 )
419  {
420  return _bad_chipids;
421  }
422 
423  else if ( strcmp(what,"HIGHEST_CHIP") == 0 )
424  {
425  return _highest_chip;
426  }
427 
428  else if ( strcmp(what,"CHIP_ID") == 0 )
429  {
430  if ( ich > _highest_chip) return -1; // no such chip
431  return _chip_id[ich];
432  }
433 
434  else if ( strcmp(what,"HIGHEST_REGION") == 0 )
435  {
436  if ( ich > _highest_chip) return -1; // no such chip
437  return _highest_region[ich];
438  }
439 
440  else if ( strcmp(what,"HIGHEST_ROW") == 0 )
441  {
442  return _highest_row_overall;
443  }
444 
445  else if ( strcmp(what,"EXCESS_DATA_BYTES") == 0 )
446  {
447  return _excess_data_bytes;
448  }
449 
450  else if ( strcmp(what,"UNEXPECTED_BYTES") == 0 )
451  {
452  if ( ich > _highest_chip) return -1; // no such chip
453  return _unexpected_bytes[ich];
454  }
455 
456  else if ( strcmp(what,"BUNCHCOUNTER") == 0 )
457  {
458  if ( ich > _highest_chip) return -1; // no such chip
459  return _bunchcounter[ich];
460  }
461 
462  else if ( strcmp(what,"HEADER_FOUND") == 0 )
463  {
464  if ( ich > _highest_chip) return -1; // no such chip
465  return _header_found[ich]?1:0;
466  }
467 
468  else if ( strcmp(what,"TRAILER_FOUND") == 0 )
469  {
470  if ( ich > _highest_chip) return -1; // no such chip
471  return _trailer_found[ich]?1:0;
472  }
473 
474  else if ( strcmp(what,"READOUT_FLAGS") == 0 )
475  {
476  if ( ich > _highest_chip) return -1; // no such chip
477  return _readout_flags[ich];
478  }
479 
480  return 0;
481 
482 }
483 
484 int oncsSub_idmvtxv0::iValue(const int chip, const int region, const int row)
485 {
486  mvtx_decode();
487 
488  if ( chip < 0 || chip > _highest_chip) return 0;
489  if ( region < 0 || region > 31 ) return 0;
490  if ( row < 0 || row > 511) return 0;
491  return chip_row[chip][row][region];
492 }
493 
494 
495 int oncsSub_idmvtxv0::iValue(const int chip, const int row)
496 {
497  mvtx_decode();
498 
499  if ( chip < 0 || chip > _highest_chip) return 0;
500  if ( row < 0 || row > 511) return 0;
501  return chip_rowmap[chip][row];
502 }
503 
504 
506 {
507 
508  identify(os);
509 
510 
511  //int x;
512  mvtx_decode();
513  os << "Highest chip: " << setw(4) << iValue(0, "HIGHEST_CHIP") +1<< endl;
514  os << "Regions: ";
515  for ( int ichip = 0; ichip < iValue(0, "HIGHEST_CHIP") +1; ichip++)
516  {
517  os << setw(4) << iValue(ichip, "HIGHEST_REGION");
518  }
519  os << endl;
520  os << "Highest populated row " << iValue(0,"HIGHEST_ROW") << endl;
521 
522  // now dump the chip info
523 
524  for ( int ichip = 0; ichip < iValue(0, "HIGHEST_CHIP")+1; ichip++) // go through the chips
525  {
526  if (iValue(ichip, "HIGHEST_REGION") == -1) continue; // skip chips we didn't see
527  os << " *** Chip " << ichip << ", chip ID " << iValue(ichip,"CHIP_ID") << " ***" << endl;
528  for ( int irow = 0; irow < iValue(0,"HIGHEST_ROW")+1; irow++)
529  {
530  bool has_hit = false;
531  for ( int iregion = 0; iregion < iValue(ichip, "HIGHEST_REGION")+1; iregion++) // check if there are any hits in this row
532  {
533  if (iValue(ichip,iregion, irow) != 0)
534  {
535  has_hit = true;
536  break;
537  }
538  }
539  if (has_hit)
540  {
541  os << " Row Region" << endl;
542  for ( int iregion = 0; iregion < iValue(ichip, "HIGHEST_REGION")+1; iregion++)
543  {
544  os << setw(4) << irow << " " << setw(4) << iregion << " | ";
545  unsigned int bits = iValue(ichip,iregion, irow);
546  for ( int i = 0; i < 32; i++)
547  {
548  if ( (bits >> i) & 1)
549  {
550  os << "X";
551  }
552  else
553  {
554  os << "-";
555  }
556  }
557  os << endl;
558  }
559  os << endl;
560  }
561  }
562  }
563 
564 }
565 
566 //copied from oncsSubevent.cc for a generic dump 12/21/17
567 void oncsSub_idmvtxv0::gdump(const int i, OSTREAM& out) const
568 {
569 
570  int *SubeventData = &SubeventHdr->data;
571  unsigned int j,l;
572  identify(out);
573 
574  int current_offset;
575  const int DWORDS_PER_WORD = 8;
576 
577  switch (i)
578  {
579  case (EVT_HEXADECIMAL):
580  //j = 0;
581  current_offset = 0;
582  while (1)
583  {
584  int dwords_remaining = getLength()-SEVTHEADERLENGTH - getPadding()/4 - current_offset; //padding is supposed to be in units of dwords, this assumes bytes
585 
586  out << SETW(5) << current_offset << " | ";
587  //for (l=0;l<DWORDS_PER_WORD;l++)
588 
589  //FELIX header
590  print_stuff(out, SubeventData[current_offset+7], 4, 16, (dwords_remaining<=7));
591  out << " ";
592 
593  //RU word 2
594  print_stuff(out, SubeventData[current_offset+7], 4, 0, (dwords_remaining<=7));
595  print_stuff(out, SubeventData[current_offset+6], 8, 0, (dwords_remaining<=6));
596  print_stuff(out, SubeventData[current_offset+5], 8, 0, (dwords_remaining<=5));
597  out << " ";
598 
599  //RU word 1
600  print_stuff(out, SubeventData[current_offset+4], 8, 0, (dwords_remaining<=4));
601  print_stuff(out, SubeventData[current_offset+3], 8, 0, (dwords_remaining<=3));
602  print_stuff(out, SubeventData[current_offset+2], 4, 16, (dwords_remaining<=2));
603  out << " ";
604 
605  //RU word 0
606  print_stuff(out, SubeventData[current_offset+2], 4, 0, (dwords_remaining<=2));
607  print_stuff(out, SubeventData[current_offset+1], 8, 0, (dwords_remaining<=1));
608  print_stuff(out, SubeventData[current_offset+0], 8, 0, (dwords_remaining<=0));
609  out << " " << std::dec << std::endl << std::setfill(' ');
610 
611  //if (current_offset>=SubeventHdr->sub_length-SEVTHEADERLENGTH - SubeventHdr->sub_padding) break;
612  //if (current_offset>=SubeventHdr->sub_length-SEVTHEADERLENGTH - SubeventHdr->sub_padding/4) break; //hack to deal with our incorrect padding in daq_device_felix.cc
613  if (dwords_remaining<8) break;
614 
615  current_offset += DWORDS_PER_WORD;
616  }
617  break;
618 
619  case (EVT_DECIMAL):
620  j = 0;
621  while (1)
622  {
623  out << std::dec << std::endl << SETW(5) << j << " | ";
624 
625  for (l=0;l<6;l++)
626  {
627  out << SETW(10) << SubeventData[j++] << " ";
629  }
631  }
632  break;
633 
634  default:
635  break;
636  }
637  out << std::endl;
638 
639 }
640