Back to home page

sPhenix code displayed by LXR

 
 

    


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

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