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