Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:20:37

0001 #include "oncsSub_idmvtxv1.h"
0002 #include <cstring>
0003 #include <bitset>
0004 #include <map>
0005 #include <vector>
0006 
0007 #include <arpa/inet.h>
0008 
0009 using namespace std;
0010 
0011 oncsSub_idmvtxv1::oncsSub_idmvtxv1(subevtdata_ptr data)
0012     :oncsSubevent_w4 (data)
0013 {
0014     _is_decoded = 0;
0015     _highest_ruid = -1;
0016     for (int ruid=0; ruid<IDMVTXV1_MAXRUID+1; ruid++)
0017     {
0018         _bad_ruchns[ruid] = 0;
0019         _lanes_active[ruid] = -1;
0020         _lane_stops[ruid] = -1;
0021         _lane_timeouts[ruid] = -1;
0022         for ( int ruchn = 0; ruchn < IDMVTXV1_MAXRUCHN+1; ruchn++)
0023         {
0024             _chip_id[ruid][ruchn] = -1;
0025             _bad_bytes[ruid][ruchn] = 0;
0026             _excess_bytes[ruid][ruchn] = 0;
0027             _bunchcounter[ruid][ruchn] = -1;
0028             _header_found[ruid][ruchn] = false;
0029             _trailer_found[ruid][ruchn] = false;
0030             _readout_flags[ruid][ruchn] = -1;
0031         }
0032     }
0033     _unexpected_felix_counters = 0;
0034     _bad_ruids = 0;
0035 }
0036 
0037 oncsSub_idmvtxv1::~oncsSub_idmvtxv1()
0038 {
0039 
0040 }
0041 
0042 
0043 typedef struct 
0044 {
0045     unsigned char d0[3][10];
0046     unsigned char counter;
0047     unsigned char ruid;
0048 }  data32;
0049 
0050 #define CHIPHEADER     1
0051 #define CHIPEMPTYFRAME 2
0052 #define DATASHORT      3
0053 #define DATALONG0      4
0054 #define DATALONG1      5
0055 
0056 int oncsSub_idmvtxv1::decode_thebit(int the_row, int encoder_id, int address) const
0057 {
0058     // the numbering "snakes" its way through a column (fig. 4.5 in the Alpide manual)
0059     //  0 1  > >    row 0 
0060     //  3 2  < <    row 1
0061     //  4 5  > >    row 2
0062     //  7 6  < <   so we need to know if we are in an even or odd row
0063     int is_an_odd_row = the_row & 1;
0064     int thebit;
0065     if ( is_an_odd_row)
0066     {
0067         thebit = (encoder_id*2) + (  ( address &1) ^ 1 );
0068     }
0069     else  
0070     {
0071         thebit = (encoder_id*2) + ( address&1);
0072     }
0073     return thebit;
0074 }
0075 
0076 void oncsSub_idmvtxv1::print_stuff(OSTREAM& out, unsigned int data, int width, int shift, bool blank) const
0077 {
0078     unsigned int mask = 0xffffffff;
0079     if (width<8) mask = ((1 << width*4)-1);
0080     if (blank)
0081         for (int i=0;i<width;i++) out << " ";
0082     else
0083         out << std::hex << SETW(width) << std::setfill('0') << ((data>>shift) & mask);
0084 }
0085 
0086 int oncsSub_idmvtxv1::encode_hit(unsigned short row, unsigned short col) const
0087 {
0088     return (row << 16) + col;
0089 }
0090 
0091 unsigned short oncsSub_idmvtxv1::decode_row(int hit) const
0092 {
0093     return hit >> 16;
0094 }
0095 
0096 unsigned short oncsSub_idmvtxv1::decode_col(int hit) const
0097 {
0098     return hit & 0xffff;
0099 }
0100 
0101 bool oncsSub_idmvtxv1::mask_contains_ruchn ( int mask, int ruchn )
0102 {
0103     if (ruchn<=0) return false; //invalid ruchn
0104     if (mask<0) return false;
0105     return (((mask >> (ruchn-1)) & 1) == 1);
0106 }
0107 
0108 int *oncsSub_idmvtxv1::mvtx_decode ()
0109 {
0110     if ( _is_decoded) return 0;
0111     _is_decoded = 1;
0112 
0113     unsigned int *payload = (unsigned int *) &SubeventHdr->data;  // here begins the payload
0114 
0115     int dlength = getDataLength() - getPadding() - 1; //padding is supposed to be in units of dwords, this assumes dwords
0116     unsigned char *the_end = ( unsigned char *) &payload[dlength];
0117 
0118     unsigned char *pos = (unsigned char *) payload;
0119 
0120     unsigned char b;
0121 
0122     vector<unsigned char> ruchn_stream[IDMVTXV1_MAXRUID+1][IDMVTXV1_MAXRUCHN+1];
0123 
0124     unsigned char felix_counter [IDMVTXV1_MAXRUID+1];
0125 
0126     for( int i=0; i < IDMVTXV1_MAXRUID+1; i++)
0127     {
0128         felix_counter[i] = 0;
0129     }
0130 
0131     while ( pos < the_end )
0132     {
0133 
0134         data32 *d32 = ( data32*) pos; 
0135 
0136         //  cout << hex << " pos = " << (unsigned long long ) pos << "  the end  " << (unsigned long long) the_end << dec << endl;
0137         if (d32->ruid > IDMVTXV1_MAXRUID)
0138         {
0139             cout << __FILE__ << " " << __LINE__ << " --- invalid ruid " << hex << (int) d32->ruid << " at pos " << (long) pos << dec << endl;
0140             _bad_ruids++;
0141             break;
0142         }
0143         else if (d32->ruid > _highest_ruid)
0144         {
0145             _highest_ruid = d32->ruid;
0146         }
0147         //FELIX counter is 8 bits, max value 256
0148         //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)
0149         int counter_increment = (d32->counter + 256 - felix_counter[d32->ruid])%256;
0150         if (counter_increment > 3)
0151         {
0152             if (d32->counter != 0)
0153             {
0154                 //cout << __FILE__ << " " << __LINE__ << " --- unexpected FELIX counter " << hex << (int) d32->counter << " following previous counter value " << felix_counter << " at pos " << (long) pos << dec << endl;
0155                 _unexpected_felix_counters++;
0156             }
0157             break;
0158         }
0159         felix_counter[d32->ruid] = d32->counter;
0160 
0161         //for (int ichnk = 0; ichnk < 3; ichnk++)
0162         for (int ichnk = 0; ichnk < counter_increment; ichnk++)
0163         {
0164             unsigned char ruchn = d32->d0[ichnk][9];
0165             if (ruchn == IDMVTXV1_RUHEADER)
0166             {
0167                 memcpy(&_lanes_active[d32->ruid],&d32->d0[ichnk][2],4);
0168             }
0169             else if (ruchn == IDMVTXV1_RUTRAILER)
0170             {
0171                 memcpy(&_lane_stops[d32->ruid],&d32->d0[ichnk][0],4);
0172                 memcpy(&_lane_timeouts[d32->ruid],&d32->d0[ichnk][4],4);
0173             }
0174             else if (ruchn > IDMVTXV1_MAXRUCHN)
0175             {
0176                 _bad_ruchns[d32->ruid]++;
0177                 cout << __FILE__ << " " << __LINE__ << " --- invalid ruchn " << hex << ruchn << ", full RU word: ";
0178                 for (int ibyte=9;ibyte>=0;ibyte--)
0179                 {
0180                     cout << setfill('0') << setw(2) << hex << (unsigned int) d32->d0[ichnk][ibyte] << " ";
0181                 }
0182                 cout << setfill(' ') << setw(0) << dec << endl;
0183             }
0184             else for ( int ibyte = 0; ibyte < 9; ibyte++)
0185             {
0186                 //cout << __FILE__ << " " << __LINE__ << hex << " --- ruchn " << ruchn << " byte " << (unsigned int) d32->d0[ichnk][ibyte] << dec << endl;
0187                 ruchn_stream[d32->ruid][ruchn].push_back(d32->d0[ichnk][ibyte]);
0188             }
0189         } // ichnk
0190 
0191         pos += sizeof(*d32);
0192     } // while (pos < the_end)
0193 
0194     //we ignore ruchn 0 (trigger information and padding words) for now
0195     /*
0196        if (ruchn_stream[0].size()!=9) for ( int ruchn = 0; ruchn < IDMVTXV1_MAXRUCHN+1; ruchn++)
0197        {
0198        cout << __FILE__ << " " << __LINE__ << " --- ruchn " << ruchn << " has " << ruchn_stream[ruchn].size() << " bytes" << endl;
0199        }
0200        */
0201 
0202     for ( int ruid = 1; ruid < IDMVTXV1_MAXRUID+1; ruid++)
0203     {
0204         for ( int ruchn = 1; ruchn < IDMVTXV1_MAXRUCHN+1; ruchn++)
0205         {
0206 
0207             bool header_seen=false;
0208             int status = 0;
0209             int ibyte_endofdata = -1;
0210             int the_region = -1;
0211             unsigned int address = 0;
0212             unsigned int encoder_id = 0;
0213             for (unsigned int ibyte = 0; ibyte < ruchn_stream[ruid][ruchn].size(); ibyte++)
0214             {
0215                 b = ruchn_stream[ruid][ruchn].at(ibyte);
0216 
0217                 //cout << __FILE__ << " " << __LINE__ << " --- ruchn " << hex << ruchn << " next value " << (unsigned int)  b << dec << " status:" << status << endl;
0218 
0219                 if (status) // we mop up what we started in the last round -
0220                     // these are all cases with more than one byte
0221                 {
0222                     switch (status)
0223                     {
0224                         case CHIPHEADER:
0225 
0226                             _bunchcounter[ruid][ruchn] = b;
0227                             //cout << __FILE__ << " " << __LINE__ << " chip header, ruchn= " << ruchn << " bunchctr= " << hex << _bunchcounter[ruchn] << dec << endl;
0228                             status = 0;
0229                             _header_found[ruid][ruchn] = true;
0230                             break;
0231 
0232                         case CHIPEMPTYFRAME:
0233 
0234                             _bunchcounter[ruid][ruchn] = b;
0235                             // cout << __FILE__ << " " << __LINE__ << " chip empty frame " << hex << ruchn << " " << _bunchcounter[ruchn] << dec << endl;
0236                             ibyte_endofdata = ibyte;
0237                             _header_found[ruid][ruchn] = true;
0238                             _trailer_found[ruid][ruchn] = true;
0239                             status = 0;
0240                             break;
0241 
0242                         case DATASHORT:
0243                             address += b;   
0244                             //cout << __FILE__ << " " << __LINE__ << " data short report, hex:" << hex << address << dec << " enc. id " << encoder_id << " address= " << address << " the_region:" << the_region << " ruchn:" << ruchn;
0245                             if ( the_region >= 0 && encoder_id >=0 ) 
0246                             {
0247                                 int the_row = (address >> 1);
0248                                 if ( the_row > 511)
0249                                 {
0250                                     cout << __FILE__ << " " << __LINE__ << " impossible row: " << the_row
0251                                         << " encoder " <<  encoder_id << " addr " << address << endl;
0252                                 }
0253                                 else
0254                                 {
0255                                     int thebit = decode_thebit(the_row, encoder_id, address);
0256                                     //cout << " row:" << the_row << " col:" << the_region*32 + thebit << endl;
0257                                     //  cout << __FILE__ << " " << __LINE__ << " the bit " << thebit << endl;
0258                                     unsigned short col = the_region*32 + thebit;
0259                                     _hit_vectors[ruid][ruchn].push_back(encode_hit(the_row,col));
0260                                 }
0261                             }
0262 
0263                             //cout << endl;
0264                             status = 0;
0265                             break;
0266 
0267                         case DATALONG0:
0268                             address += b;   
0269                             status = DATALONG1;
0270                             break;
0271 
0272                         case DATALONG1:
0273                             if ( (b & 0x80) != 0) //required to be 0
0274                             {
0275                                 //cout << __FILE__ << " " << __LINE__ << " unexpected word " << hex << (unsigned int) b << dec << " at ibyte " << ibyte << endl;
0276                                 _bad_bytes[ruid][ruchn]++;
0277                             }
0278                             //cout << __FILE__ << " " << __LINE__ << " data long report, hex:" << hex << address << dec << " enc. id " << encoder_id << " address= " << address << " the_region:" << the_region << " ruchn:" << ruchn << endl;
0279                             // Loop over the hits in the cluster. The pixel specified by the address always has a hit.
0280                             // The next 7 pixels (in priority encoder order) have hits if the corresponding bit in this byte is high. 
0281                             // See ALPIDE manual section 3.4.1 on DATA LONG: page 63.
0282                             for (int ihit = 0; ihit<8; ihit++)
0283                             {
0284                                 if (ihit==0 || ((b >> (ihit-1)) & 1))
0285                                 {
0286                                     int hit_address = address + ihit;
0287                                     if ( the_region >= 0 && encoder_id >=0 ) 
0288                                     {
0289                                         int the_row = (hit_address >> 1);
0290                                         if ( the_row > 511)
0291                                         {
0292                                             cout << __FILE__ << " " << __LINE__ << " impossible row: " << the_row
0293                                                 << " encoder " <<  encoder_id << " addr " << hit_address << endl;
0294                                         }
0295                                         else
0296                                         {
0297                                             int thebit = decode_thebit(the_row, encoder_id, hit_address);
0298                                             //cout << " row:" << the_row << " col:" << the_region*32 + thebit << endl;
0299                                             //  cout << __FILE__ << " " << __LINE__ << " the bit " << thebit << endl;
0300                                             unsigned short col = the_region*32 + thebit;
0301                                             _hit_vectors[ruid][ruchn].push_back(encode_hit(the_row,col));
0302                                         }
0303                                     }
0304                                 }
0305                             }
0306                             status = 0;
0307                             break;
0308                     }
0309                     continue;
0310                 }
0311 
0312                 if (ibyte_endofdata != -1) break;
0313 
0314                 if ( b == 0xff)  // Idle byte, skip
0315                 {
0316                     //cout << __FILE__ << " " << __LINE__ << " IDLE byte " << hex << (unsigned int)  b << dec << endl;
0317                     status = 0;
0318                 }
0319 
0320                 else if ( ( b >> 4) == 0xa) // we have a chip header
0321                 {
0322                     _chip_id[ruid][ruchn] = ( b & 0xf);
0323                     header_seen = true;
0324                     status = CHIPHEADER;
0325                 }
0326 
0327                 else if ( ( b >> 4) == 0xb) // we have a chip trailer
0328                 {
0329                     // cout << __FILE__ << " " << __LINE__ << " chip trailer, ruchn= " << hex << ruchn << dec << endl;
0330                     // break out of the loop, done with this chip
0331                     ibyte_endofdata = ibyte;
0332                     _trailer_found[ruid][ruchn] = true;
0333                     if (!_header_found[ruid][ruchn]) // shouldn't see a trailer without having seen a header
0334                     {
0335                         _bad_bytes[ruid][ruchn]++;
0336                     }
0337                     else
0338                     {
0339                         _readout_flags[ruid][ruchn] = (b & 0xf);
0340                     }
0341                     break;
0342                 }
0343 
0344                 else if ( ( b >> 4) == 0xE) // we have a chip empty frame
0345                 {
0346                     _chip_id[ruid][ruchn] = ( b & 0xf);
0347                     header_seen = true;
0348                     status = CHIPEMPTYFRAME;
0349                 }
0350 
0351                 else if ( ( b >> 5) == 0x6) // we have a region header
0352                 {
0353                     unsigned int region_id = (b & 0x1f);
0354                     if ( region_id <32)
0355                     {
0356                         the_region = region_id;
0357                     }
0358                     else //this is impossible since the region ID is 5 bits
0359                     {
0360                         cout << __FILE__ << " " << __LINE__ << " wrong region header, id=  " << hex << region_id << dec << endl;
0361                     }
0362                 }
0363 
0364                 else if ( ( b >> 6) == 0x1) // we have a DATA short report
0365                 {
0366                     encoder_id = ( b>>2) & 0xf;
0367                     address = (b & 0x3) << 8;
0368                     status = DATASHORT;
0369                 }
0370 
0371                 else if ( ( b >> 6) == 0x0) // we have a DATA long report
0372                 {
0373                     encoder_id = ( b>>2) & 0xf;
0374                     address = (b & 0x3) << 8;
0375                     status = DATALONG0;
0376                 }
0377 
0378                 else if ( b == 0xF1) // we have a BUSY on
0379                 {
0380                     //cout << __FILE__ << " " << __LINE__ << " Busy on "  << endl;
0381                 }
0382 
0383                 else if ( b == 0xF0) // we have a BUSY off
0384                 {
0385                     //cout << __FILE__ << " " << __LINE__ << " Busy off "  << endl;
0386                 }
0387 
0388                 else
0389                 {
0390                     //cout << __FILE__ << " " << __LINE__ << " unexpected word " << hex << (unsigned int) b << dec << " at ibyte " << ibyte << endl;
0391                     _bad_bytes[ruid][ruchn]++;
0392                 }
0393                 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
0394 
0395             } // ibyte
0396 
0397             //cout << __FILE__ << " " << __LINE__ << "  ruchn " << ruchn << "  ibyte_endofdata " << ibyte_endofdata << endl;
0398             for (unsigned int ibyte = ibyte_endofdata+1; ibyte < ruchn_stream[ruid][ruchn].size(); ibyte++)
0399             {
0400                 b = ruchn_stream[ruid][ruchn].at(ibyte);
0401                 if (b!=0)
0402                 {
0403                     //cout << __FILE__ << " " << __LINE__ << " --- ruchn " << hex << ruchn << " unexpected nonzero value " << (unsigned int)  b << dec << " at ibyte " << ibyte << " after ibyte_endofdata " << ibyte_endofdata << endl;
0404                     _excess_bytes[ruid][ruchn]++;
0405                 }
0406             }
0407         } // ruchn
0408     } // ruid
0409 
0410 
0411     return 0;
0412 }
0413 
0414 int oncsSub_idmvtxv1::iValue(const int ruid, const char *what)
0415 {
0416 
0417   if ( strcmp(what,"MAXRUID") == 0 )
0418     {
0419       return IDMVTXV1_MAXRUID;
0420     }
0421   else if ( strcmp(what,"MAXRUCHN") == 0 )
0422     {
0423       return IDMVTXV1_MAXRUCHN;
0424     }
0425       
0426   
0427   mvtx_decode();
0428   
0429   if ( strcmp(what,"UNEXPECTED_FELIX_COUNTERS") == 0 )
0430     {
0431       return _unexpected_felix_counters;
0432     }
0433   
0434   else if ( strcmp(what,"BAD_RUIDS") == 0 )
0435     {
0436       return _bad_ruids;
0437     }
0438   
0439   if (ruid > _highest_ruid) return -1; // no such RU
0440   if (_lanes_active[ruid]==-1) return -1; // no such RU
0441   
0442   if ( strcmp(what,"BAD_RUCHNS") == 0 )
0443     {
0444       return _bad_ruchns[ruid];
0445     }
0446   
0447   else if ( strcmp(what,"LANE_STOPS") == 0 )
0448     {
0449       return _lane_stops[ruid];
0450     }
0451   
0452   else if ( strcmp(what,"LANE_TIMEOUTS") == 0 )
0453     {
0454       return _lane_timeouts[ruid];
0455     }
0456   
0457   return 0;
0458 }
0459 
0460 int oncsSub_idmvtxv1::iValue(const int ruid)
0461 {
0462     mvtx_decode();
0463 
0464     if (ruid > _highest_ruid) return -1; // no such RU
0465     return _lanes_active[ruid];
0466 }
0467 
0468 int oncsSub_idmvtxv1::iValue(const int ruid, const int ruchn, const char *what)
0469 {
0470     mvtx_decode();
0471 
0472     if (ruid > _highest_ruid) return -1; // no such RU
0473     if (_lanes_active[ruid]==-1) return -1; // no such RU
0474 
0475     if ( strcmp(what,"CHIP_ID") == 0 )
0476     {
0477         return _chip_id[ruid][ruchn];
0478     }
0479 
0480     else if ( strcmp(what,"BAD_BYTES") == 0 )
0481     {
0482         return _bad_bytes[ruid][ruchn];
0483     }
0484 
0485     else if ( strcmp(what,"EXCESS_BYTES") == 0 )
0486     {
0487         return _excess_bytes[ruid][ruchn];
0488     }
0489 
0490     else if ( strcmp(what,"BUNCHCOUNTER") == 0 )
0491     {
0492         return _bunchcounter[ruid][ruchn];
0493     }
0494 
0495     else if ( strcmp(what,"HEADER_FOUND") == 0 )
0496     {
0497         return _header_found[ruid][ruchn]?1:0;
0498     }
0499 
0500     else if ( strcmp(what,"TRAILER_FOUND") == 0 )
0501     {
0502         return _trailer_found[ruid][ruchn]?1:0;
0503     }
0504 
0505     else if ( strcmp(what,"READOUT_FLAGS") == 0 )
0506     {
0507         return _readout_flags[ruid][ruchn];
0508     }
0509 
0510     return 0;
0511 }
0512 
0513 int oncsSub_idmvtxv1::iValue(const int ruid, const int ruchn)
0514 {
0515     mvtx_decode();
0516 
0517     if (ruid > _highest_ruid) return -1; // no such RU
0518     if (_lanes_active[ruid]==-1) return -1; // no such RU
0519     if (!mask_contains_ruchn(_lanes_active[ruid],ruchn)) return -1; // no such RU channel
0520     return _hit_vectors[ruid][ruchn].size();
0521 }
0522 
0523 int oncsSub_idmvtxv1::iValue(const int ruid, const int ruchn, const int i)
0524 {
0525     mvtx_decode();
0526 
0527     if (ruid > _highest_ruid) return -1; // no such RU
0528     if (_lanes_active[ruid]==-1) return -1; // no such RU
0529     if (!mask_contains_ruchn(_lanes_active[ruid],ruchn)) return -1; // no such RU channel
0530     return _hit_vectors[ruid][ruchn].at(i);
0531 }
0532 
0533 void  oncsSub_idmvtxv1::dump ( OSTREAM& os )
0534 {
0535 
0536     identify(os);
0537 
0538     mvtx_decode();
0539     bool first;
0540     for (int ruid=0; ruid<IDMVTXV1_MAXRUID+1; ruid++)
0541     {
0542         if (iValue(ruid)!=-1)
0543         {
0544             os << "RU ID: " << ruid;
0545             os << ", bad_ruchns=" << iValue(ruid,"BAD_RUCHNS");
0546             os << hex << setfill('0');
0547             os << ", lanes_active 0x" << setw(7) << iValue(ruid);
0548             os << dec;
0549             first=true;
0550             os << " (";
0551             for ( int ruchn = 0; ruchn < IDMVTXV1_MAXRUCHN+1; ruchn++)
0552             {
0553                 if (mask_contains_ruchn(iValue(ruid),ruchn))
0554                 {
0555                     if (!first)
0556                         os << ", ";
0557                     os << ruchn;
0558                     first = false;
0559                 }
0560             }
0561             os << hex << setfill('0');
0562             os << "), lane_stops=0x" << setw(7) << iValue(ruid,"LANE_STOPS");
0563             os << dec;
0564             first=true;
0565             os << " (";
0566             for ( int ruchn = 0; ruchn < IDMVTXV1_MAXRUCHN+1; ruchn++)
0567             {
0568                 if (mask_contains_ruchn(iValue(ruid,"LANE_STOPS"),ruchn))
0569                 {
0570                     if (!first)
0571                         os << ", ";
0572                     os << ruchn;
0573                     first = false;
0574                 }
0575             }
0576             os << hex << setfill('0');
0577             os << "), lane_timeouts=0x" << setw(7) << iValue(ruid,"LANE_TIMEOUTS");
0578             os << dec;
0579             first=true;
0580             os << " (";
0581             for ( int ruchn = 0; ruchn < IDMVTXV1_MAXRUCHN+1; ruchn++)
0582             {
0583                 if (mask_contains_ruchn(iValue(ruid,"LANE_TIMEOUTS"),ruchn))
0584                 {
0585                     if (!first)
0586                         os << ", ";
0587                     os << ruchn;
0588                     first = false;
0589                 }
0590             }
0591             os << ")";
0592             os << dec << setfill(' ') << endl;
0593             for ( int ruchn = 0; ruchn < IDMVTXV1_MAXRUCHN+1; ruchn++)
0594             {
0595                 if (iValue(ruid,ruchn)!=-1)
0596                 {
0597                     os << "RU channel " << setw(2) << ruchn;
0598                     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");
0599                     os << " bunchcounter=" << setw(3) << iValue(ruid,ruchn,"BUNCHCOUNTER") << " flags=" << iValue(ruid,ruchn,"READOUT_FLAGS");
0600                     os << ", chip ID " << iValue(ruid,ruchn,"CHIP_ID") << ", " << iValue(ruid,ruchn) << " hits: ";
0601                     for (int i=0;i<iValue(ruid,ruchn);i++)
0602                     {
0603                         int hit = iValue(ruid,ruchn,i);
0604                         os << "(row " << decode_row(hit) << ", col " << decode_col(hit) << ") ";
0605                     }
0606                     os << endl;
0607                 }
0608             }
0609         }
0610     }
0611 }
0612 
0613 //copied from oncsSubevent.cc for a generic dump 12/21/17
0614 void oncsSub_idmvtxv1::gdump(const int i, OSTREAM& out) const
0615 {
0616 
0617     int *SubeventData = &SubeventHdr->data;
0618     unsigned int j;
0619     int l;
0620 
0621     identify(out);
0622 
0623     int current_offset;
0624     const int DWORDS_PER_WORD = 8;
0625 
0626     switch (i)
0627     {
0628         case (EVT_HEXADECIMAL):
0629             //j = 0;
0630             current_offset = 0;
0631             while (1)
0632             {
0633                 //int dwords_remaining = getLength()-SEVTHEADERLENGTH - getPadding()/4 - current_offset; //padding is supposed to be in units of dwords, this assumes bytes
0634                 int dwords_remaining = getLength()-SEVTHEADERLENGTH - getPadding() - current_offset; //padding is supposed to be in units of dwords, this assumes dwords
0635 
0636                 out << SETW(5) << current_offset << " |  ";
0637                 //for (l=0;l<DWORDS_PER_WORD;l++)
0638 
0639                 //FELIX header
0640                 print_stuff(out, SubeventData[current_offset+7], 4, 16, (dwords_remaining<=7));
0641                 out << " ";
0642 
0643                 //RU word 2
0644                 print_stuff(out, SubeventData[current_offset+7], 4, 0, (dwords_remaining<=7));
0645                 print_stuff(out, SubeventData[current_offset+6], 8, 0, (dwords_remaining<=6));
0646                 print_stuff(out, SubeventData[current_offset+5], 8, 0, (dwords_remaining<=5));
0647                 out << " ";
0648 
0649                 //RU word 1
0650                 print_stuff(out, SubeventData[current_offset+4], 8, 0, (dwords_remaining<=4));
0651                 print_stuff(out, SubeventData[current_offset+3], 8, 0, (dwords_remaining<=3));
0652                 print_stuff(out, SubeventData[current_offset+2], 4, 16, (dwords_remaining<=2));
0653                 out << " ";
0654 
0655                 //RU word 0
0656                 print_stuff(out, SubeventData[current_offset+2], 4, 0, (dwords_remaining<=2));
0657                 print_stuff(out, SubeventData[current_offset+1], 8, 0, (dwords_remaining<=1));
0658                 print_stuff(out, SubeventData[current_offset+0], 8, 0, (dwords_remaining<=0));
0659                 out << " " << std::dec << std::endl << std::setfill(' ');
0660 
0661                 if (dwords_remaining<8) break;
0662 
0663                 current_offset += DWORDS_PER_WORD;
0664             }
0665             break;
0666 
0667         case (EVT_DECIMAL):
0668             j = 0;
0669             while (1)
0670             {
0671                 out << std::dec << std::endl << SETW(5) << j << " |  ";
0672 
0673                 for (l=0;l<6;l++)
0674                 {
0675                     out << SETW(10) << SubeventData[j++] << " ";
0676                     if (j>=SubeventHdr->sub_length-SEVTHEADERLENGTH - SubeventHdr->sub_padding) break;
0677                 }
0678                 if (j>=SubeventHdr->sub_length-SEVTHEADERLENGTH - SubeventHdr->sub_padding) break;
0679             }
0680             break;
0681 
0682         default: 
0683             break;
0684     }
0685     out << std::endl;
0686 
0687 }
0688