CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_10_patch1/src/EventFilter/CSCRawToDigi/src/CSCDCCExaminer.cc

Go to the documentation of this file.
00001 #include "EventFilter/CSCRawToDigi/interface/CSCDCCExaminer.h"
00002 #include <string.h>
00003 #include <iomanip>
00004 using namespace std;
00005 
00006 void CSCDCCExaminer::crcALCT(bool enable){
00007   checkCrcALCT = enable;
00008   if( checkCrcALCT )
00009     sERROR[10] = "ALCT CRC Error                                   ";
00010   else
00011     sERROR[10] = "ALCT CRC Error ( disabled )                      ";
00012 }
00013 
00014 void CSCDCCExaminer::crcTMB(bool enable){
00015   checkCrcTMB = enable;
00016   if( checkCrcTMB )
00017     sERROR[15] = "TMB CRC Error                                    ";
00018   else
00019     sERROR[15] = "TMB CRC Error ( disabled )                       ";
00020 }
00021 
00022 void CSCDCCExaminer::crcCFEB(bool enable){
00023   checkCrcCFEB = enable;
00024   if( checkCrcCFEB )
00025     sERROR[18] = "CFEB CRC Error                                   ";
00026   else
00027     sERROR[18] = "CFEB CRC Error ( disabled )                      ";
00028 }
00029 
00030 void CSCDCCExaminer::modeDDU(bool enable){
00031   modeDDUonly = enable;
00032   if( modeDDUonly) {
00033     sERROR[25] = "DCC Trailer Missing                              ";
00034     sERROR[26] = "DCC Header Missing                               ";
00035   } else {
00036     sERROR[25] = "DCC Trailer Missing (disabled)                   ";
00037     sERROR[26] = "DCC Header Missing (disabled)                    ";
00038   }
00039 
00040 }
00041 
00042 
00043 CSCDCCExaminer::CSCDCCExaminer(ExaminerMaskType mask):nERRORS(29),nWARNINGS(5),nPAYLOADS(12),nSTATUSES(23),sERROR(nERRORS),sWARNING(nWARNINGS),sERROR_(nERRORS),sWARNING_(nWARNINGS),sDMBExpectedPayload(nPAYLOADS),sDMBEventStaus(nSTATUSES),examinerMask(mask){
00044   cout.redirect(std::cout); cerr.redirect(std::cerr);
00045 
00046   sERROR[0] = " Any errors                                       ";
00047   sERROR[1] = " DDU Trailer Missing                              ";
00048   sERROR[2] = " DDU Header Missing                               ";
00049   sERROR[3] = " DDU CRC Error (not yet implemented)              ";
00050   sERROR[4] = " DDU Word Count Error                             ";
00051   sERROR[5] = " DMB Trailer Missing                              ";
00052   sERROR[6] = " DMB Header Missing                               ";
00053   sERROR[7] = " ALCT Trailer Missing                             ";
00054   sERROR[8] = " ALCT Header Missing                              ";
00055   sERROR[9] = " ALCT Word Count Error                            ";
00056   sERROR[10] = "ALCT CRC Error                                   ";
00057   sERROR[11] = "ALCT Trailer Bit Error                           ";
00058   // ^^^ This is due to seeing many events in ddu293 (also, some in ddu294)
00059   // with some bits in the 1st ALCT D-Header being lost. This causes a chain of errors:
00060   // - TMB Trailer is not identified and TMB word count mismatch occur when Trailer is found
00061   // - CFEB sample count is not reset on ALCT Trailer.
00062   // To merge all these errors in one,
00063   // the D-signature in the 1st ALCT Trailer will not be required for identifying the ALCT Trailer;
00064   // However, if these bits are found to be missing, ERROR[11] will be flagged.
00065   // This is just a temporary patch to make the output look less clattered.
00066   sERROR[12] = "TMB Trailer Missing                              ";
00067   sERROR[13] = "TMB Header Missing                               ";
00068   sERROR[14] = "TMB Word Count Error                             ";
00069   sERROR[15] = "TMB CRC Error                                    ";
00070   sERROR[16] = "CFEB Word Count Per Sample Error                 ";
00071   sERROR[17] = "CFEB Sample Count Error                          ";
00072   sERROR[18] = "CFEB CRC Error                                   ";
00073   sERROR[19] = "DDU Event Size Limit Error                       ";
00074   sERROR[20] = "C-Words                                          ";
00075   sERROR[21] = "ALCT DAV Error                                   ";
00076   sERROR[22] = "TMB DAV Error                                    ";
00077   sERROR[23] = "CFEB DAV Error                                   ";
00078   sERROR[24] = "DMB Active Error                                 ";
00079   sERROR[25] = "DCC Trailer Missing                              ";
00080   sERROR[26] = "DCC Header Missing                               ";
00081   sERROR[27] = "DMB DAV vs. DMB Active mismatch Error            ";
00082   sERROR[28] = "Extra words between DDU Header and first DMB header";
00083 
00084   //    sERROR[21] = "DDU Header vs. Trailer mismatch for DAV or Avtive"; // oboslete since 16.09.05
00085 
00086   sWARNING[0] = " Extra words between DDU Trailer and DDU Header ";
00087   sWARNING[1] = " DDU Header Incomplete                          ";
00088 
00089   sDMBExpectedPayload[0]  = "CFEB1_ACTIVE";
00090   sDMBExpectedPayload[1]  = "CFEB2_ACTIVE";
00091   sDMBExpectedPayload[2]  = "CFEB3_ACTIVE";
00092   sDMBExpectedPayload[3]  = "CFEB4_ACTIVE";
00093   sDMBExpectedPayload[4]  = "CFEB5_ACTIVE";
00094   sDMBExpectedPayload[5]  = "ALCT_DAV";
00095   sDMBExpectedPayload[6]  = "TMB_DAV";
00096   sDMBExpectedPayload[7]  = "CFEB1_DAV";
00097   sDMBExpectedPayload[8]  = "CFEB2_DAV";
00098   sDMBExpectedPayload[9]  = "CFEB3_DAV";
00099   sDMBExpectedPayload[10] = "CFEB4_DAV";
00100   sDMBExpectedPayload[11] = "CFEB5_DAV";
00101 
00102   sDMBEventStaus[0]  = "ALCT_FIFO_FULL";
00103   sDMBEventStaus[1]  = "TMB_FIFO_FULL";
00104   sDMBEventStaus[2]  = "CFEB1_FIFO_FULL";
00105   sDMBEventStaus[3]  = "CFEB2_FIFO_FULL";
00106   sDMBEventStaus[4]  = "CFEB3_FIFO_FULL";
00107   sDMBEventStaus[5]  = "CFEB4_FIFO_FULL";
00108   sDMBEventStaus[6]  = "CFEB5_FIFO_FULL";
00109   sDMBEventStaus[7]  = "ALCT_START_TIMEOUT";
00110   sDMBEventStaus[8]  = "TMB_START_TIMEOUT";
00111   sDMBEventStaus[9]  = "CFEB1_START_TIMEOUT";
00112   sDMBEventStaus[10] = "CFEB2_START_TIMEOUT";
00113   sDMBEventStaus[11] = "CFEB3_START_TIMEOUT";
00114   sDMBEventStaus[12] = "CFEB4_START_TIMEOUT";
00115   sDMBEventStaus[13] = "CFEB5_START_TIMEOUT";
00116   sDMBEventStaus[14] = "ALCT_END_TIMEOUT";
00117   sDMBEventStaus[15] = "TMB_END_TIMEOUT";
00118   sDMBEventStaus[16] = "CFEB1_END_TIMEOUT";
00119   sDMBEventStaus[17] = "CFEB2_END_TIMEOUT";
00120   sDMBEventStaus[18] = "CFEB3_END_TIMEOUT";
00121   sDMBEventStaus[19] = "CFEB4_END_TIMEOUT";
00122   sDMBEventStaus[20] = "CFEB5_END_TIMEOUT";
00123   sDMBEventStaus[21] = "CFEB Active-DAV mismatch";
00124   sDMBEventStaus[22] = "B-words found";
00125 
00126   sERROR_[0] = " Any errors: 00";
00127   sERROR_[1] = " DDU Trailer Missing: 01";
00128   sERROR_[2] = " DDU Header Missing: 02";
00129   sERROR_[3] = " DDU CRC Error (not yet implemented): 03";
00130   sERROR_[4] = " DDU Word Count Error: 04";
00131   sERROR_[5] = " DMB Trailer Missing: 05";
00132   sERROR_[6] = " DMB Header Missing: 06";
00133   sERROR_[7] = " ALCT Trailer Missing: 07";
00134   sERROR_[8] = " ALCT Header Missing: 08";
00135   sERROR_[9] = " ALCT Word Count Error: 09";
00136   sERROR_[10] = "ALCT CRC Error: 10";
00137   sERROR_[11] = "ALCT Trailer Bit Error: 11";
00138   sERROR_[12] = "TMB Trailer Missing: 12";
00139   sERROR_[13] = "TMB Header Missing: 13";
00140   sERROR_[14] = "TMB Word Count Error: 14";
00141   sERROR_[15] = "TMB CRC Error: 15";
00142   sERROR_[16] = "CFEB Word Count Per Sample Error: 16";
00143   sERROR_[17] = "CFEB Sample Count Error: 17";
00144   sERROR_[18] = "CFEB CRC Error: 18";
00145   sERROR_[19] = "DDU Event Size Limit Error: 19";
00146   sERROR_[20] = "C-Words: 20";
00147   sERROR_[21] = "ALCT DAV Error: 21";
00148   sERROR_[22] = "TMB DAV Error: 22";
00149   sERROR_[23] = "CFEB DAV Error: 23";
00150   sERROR_[24] = "DMB Active Error: 24";
00151   sERROR_[25] = "DCC Trailer Missing: 25";
00152   sERROR_[26] = "DCC Header Missing: 26";
00153   sERROR_[27] = "DMB DAV vs. DMB Active mismatch Error: 27";
00154   sERROR_[28] = "Extra words between DDU Header and first DMB header: 28";
00155   //    sERROR_[21] = "DDU Header vs. Trailer mismatch for DAV or Avtive: 21"; // oboslete since 16.09.05
00156 
00157   sWARNING_[0] = " Extra words between DDU Trailer and DDU Header: 00";
00158   sWARNING_[1] = " DDU Header Incomplete: 02";
00159 
00160   fDCC_Header  = false;
00161   fDCC_Trailer = false;
00162   fDDU_Header  = false;
00163   fDDU_Trailer = false;
00164   fDMB_Header  = false;
00165   fDMB_Trailer = false;
00166   fALCT_Header = false;
00167   fTMB_Header  = false;
00168   fALCT_Format2007 = true;
00169   fTMB_Format2007  = true;
00170 
00171   cntDDU_Headers  = 0;
00172   cntDDU_Trailers = 0;
00173   cntCHAMB_Headers.clear();
00174   cntCHAMB_Trailers.clear();
00175 
00176   DAV_ALCT = false;
00177   DAV_TMB  = false;
00178   DAV_CFEB = 0;
00179   DMB_Active  = 0;
00180   nDMBs = 0;
00181   DDU_WordsSinceLastHeader     = 0;
00182   DDU_WordCount                = 0;
00183   DDU_WordMismatch_Occurrences = 0;
00184   DDU_WordsSinceLastTrailer    = 0;
00185   ALCT_ZSE                     = 0;
00186   nWG_round_up                 = 0;
00187 
00188   TMB_WordsRPC  = 0;
00189   TMB_Firmware_Revision = 0;
00190   zeroCounts();
00191 
00192   checkCrcALCT = false; ALCT_CRC=0;
00193   checkCrcTMB  = false; TMB_CRC=0;
00194   checkCrcCFEB = false; CFEB_CRC=0;
00195 
00196   modeDDUonly = false;
00197   sourceID    = 0xFFF;
00198   currentChamber = -1;
00199 
00200   //headerDAV_Active = -1; // Trailer vs. Header check // Obsolete since 16.09.05
00201 
00202   clear();
00203   buf_1 = &(tmpbuf[0]);
00204   buf0  = &(tmpbuf[4]);
00205   buf1  = &(tmpbuf[8]);
00206   buf2  = &(tmpbuf[12]);
00207 
00208   bzero(tmpbuf, sizeof(uint16_t)*16);
00209 }
00210 
00211 int32_t CSCDCCExaminer::check(const uint16_t* &buffer, int32_t length){
00212   if( length<=0 ) return -1;
00213 
00215   buffer_start = buffer;
00216 
00217   
00219   bool fTMB_Scope_Start = false;
00220   bool fTMB_MiniScope_Start = false; 
00221   bool fTMB_RPC_Start = false;
00222   bool fTMB_BlockedCFEBs_Start = false;
00223  
00224   bool fTMB_Scope = false; 
00225   bool fTMB_MiniScope = false; 
00226   bool fTMB_RPC = false;
00227   bool fTMB_BlockedCFEBs = false;
00228 
00229   fTMB_Scope = fTMB_Scope && true; // WARNING in 5_0_X
00230 
00231   while( length>0 ){
00232     // == Store last 4 read buffers in pipeline-like memory (note that memcpy works quite slower!)
00233     buf_2 = buf_1;         //  This bufer was not needed so far
00234     buf_1 = buf0;
00235     buf0  = buf1;
00236     buf1  = buf2;
00237     buf2  = buffer;
00238 
00239     // check for too long event
00240     if(!fERROR[19] && DDU_WordsSinceLastHeader>100000 ){
00241       fERROR[19] = true;
00242       bERROR    |= 0x80000;
00243     }
00244 
00245     // increment counter of 64-bit words since last DDU Header
00246     // this counter is reset if DDU Header is found
00247     if ( fDDU_Header ) { ++DDU_WordsSinceLastHeader; }
00248 
00249     // increment counter of 64-bit words since last DDU Trailer
00250     // this counter is reset if DDU Trailer is found
00251     if ( fDDU_Trailer ) {++DDU_WordsSinceLastTrailer; }
00252 
00255     if ( fALCT_Header ) {
00257         if(ALCT_ZSE){
00258           for(int g=0; g<4; g++){
00259              if(buf0[g]==0x1000){
00260                ALCT_WordsSinceLastHeader = ALCT_WordsSinceLastHeader + nWG_round_up;
00261           } 
00262           else if(buf0[g]!=0x3000) ALCT_WordsSinceLastHeader = ALCT_WordsSinceLastHeader + 1;
00263          } 
00264         }
00265         else ALCT_WordsSinceLastHeader = ALCT_WordsSinceLastHeader + 4;
00267         ALCT_WordsSinceLastHeaderZeroSuppressed = ALCT_WordsSinceLastHeaderZeroSuppressed + 4;
00268     }
00269 
00270     // increment counter of 16-bit words since last DMB*TMB Header match
00271     // this counter is reset if TMB Header is found right after DMB Header or ALCT Trailer
00272     if ( fTMB_Header ) { TMB_WordsSinceLastHeader = TMB_WordsSinceLastHeader + 4; }
00273 
00274     // increment counter of 16-bit words since last of DMB Header, ALCT Trailer, TMB Trailer,
00275     // CFEB Sample Trailer, CFEB B-word; this counter is reset by all these conditions
00276     if ( fDMB_Header ) { CFEB_SampleWordCount = CFEB_SampleWordCount + 4; }
00277 
00278     // If DDU header is missing we set unphysical 0xFFF value for DDU id
00279     if( !fDDU_Header ){ sourceID=0xFFF; }
00280 
00281 
00282     if (!modeDDUonly) {
00283       // DCC Header 1 && DCC Header 2
00284       // =VB= Added support for Sep. 2008 CMS DAQ DCC format
00285       if ( ( ( (buf0[3]&0xF000) == 0x5000 && (buf0[0]&0x00FF) == 0x005F )
00286         ||
00287            ( (buf0[3]&0xF000) == 0x5000 && (buf0[0]&0x000F) == 0x0008 ) )
00288          &&
00289           // =VB= Why 0xD900 signature word if only 0xD part is constant???
00290           // (buf1[3]&0xFF00) == 0xD900 ) 
00291           (buf1[3]&0xF000) == 0xD000 )
00292         {
00293         if( fDCC_Header ){
00294           // == Another DCC Header before encountering DCC Trailer!
00295           fERROR[25]=true;
00296           bERROR|=0x2000000;
00297           fERROR[0]=true;
00298           bERROR|=0x1;
00299           cerr<<"\n\nDCC Header Occurrence ";
00300           cerr<<"  ERROR 25    "<<sERROR[25]<<endl;
00301           fDDU_Header = false;
00302 
00303           // go backward for 3 DDU words ( buf2, buf1, and buf0 )
00304           buffer-=12;
00305           buf_1 = &(tmpbuf[0]);  // Just for safety
00306           buf0  = &(tmpbuf[4]);  // Just for safety
00307           buf1  = &(tmpbuf[8]);  // Just for safety
00308           buf2  = &(tmpbuf[12]); // Just for safety
00309           bzero(tmpbuf,sizeof(uint16_t)*16);
00310           sync_stats();
00311           return length+12;
00312         }
00313 
00314     fDCC_Header  = true;
00315     clear();
00316           }
00317         }
00318     // == Check for Format Control Words, set proper flags, perform self-consistency checks
00319 
00320     // C-words anywhere besides DDU Header
00321     if( fDDU_Header && ( (buf0[0]&0xF000)==0xC000 || (buf0[1]&0xF000)==0xC000 || (buf0[2]&0xF000)==0xC000 || (buf0[3]&0xF000)==0xC000 ) &&
00322         ( /*buf_1[0]!=0x8000 ||*/ buf_1[1]!=0x8000 || buf_1[2]!=0x0001 || buf_1[3]!=0x8000 ) ){
00323       fERROR[0]  = true;
00324       bERROR    |= 0x1;
00325       fERROR[20] = true;
00326       bERROR    |= 0x100000;
00327           // fCHAMB_ERR[20].insert(currentChamber);
00328           // bCHAMB_ERR[currentChamber] |= 0x100000;
00329       cerr<<"\nDDU Header Occurrence = "<<cntDDU_Headers;
00330       cerr<<"  ERROR 20 "<<sERROR[20]<<endl;
00331     }
00332 
00333     // == DDU Header found
00334     if( /*buf0[0]==0x8000 &&*/ buf0[1]==0x8000 && buf0[2]==0x0001 && buf0[3]==0x8000 ){
00335       // headerDAV_Active = (buf1[1]<<16) | buf1[0]; // Obsolete since 16.09.05
00337         checkDAVs();
00338         checkTriggerHeadersAndTrailers();
00340 
00341       if( fDDU_Header ){
00342         // == Another DDU Header before encountering DDU Trailer!
00343         fERROR[1]=true;
00344         bERROR|=0x2;
00345         fERROR[0] = true;
00346         bERROR|=0x1;
00347         cerr<<"\n\nDDU Header Occurrence = "<<cntDDU_Headers;
00348         cerr<<"  ERROR 1    "<<sERROR[1]<<endl;
00349         fDDU_Header = false;
00350 
00351         // Part of work for chambers that hasn't been done in absent trailer
00352         if( fDMB_Header || fDMB_Trailer ){
00353           fERROR[5] = true;
00354           bERROR   |= 0x20;
00355           // Since here there are no chances to know what this chamber was, force it to be -2
00356           if( currentChamber == -1 ) currentChamber = -2;
00357           fCHAMB_ERR[5].insert(currentChamber);
00358           bCHAMB_ERR[currentChamber] |= 0x20;
00359           fCHAMB_ERR[0].insert(currentChamber);
00360           bCHAMB_ERR[currentChamber] |= 0x1;
00361           cerr<<"\n\nDDU Header Occurrence = "<<cntDDU_Headers;
00362           cerr<<"  ERROR 5    "<<sERROR[5]<<endl;
00363         }       // One of DMB Trailers is missing ( or both )
00364         fDMB_Header  = false;
00365         fDMB_Trailer = false;
00366 
00367         if( DMB_Active!=nDMBs ){
00368           fERROR[24] = true;
00369           bERROR    |= 0x1000000;
00370         }
00371         DMB_Active = 0;
00372         nDMBs = 0;
00373 
00374         // Unknown chamber denoted as -2
00375         // If it still remains in any of errors - put it in error 0
00376         for(int err=1; err<nERRORS; ++err)
00377           if( fCHAMB_ERR[err].find(-2) != fCHAMB_ERR[err].end() ){
00378             fCHAMB_ERR[0].insert(-2);
00379             bCHAMB_ERR[-2] |= 0x1;
00380           }
00381 
00382         bDDU_ERR[sourceID] |= bERROR;
00383         bDDU_WRN[sourceID] |= bWARNING;
00384 
00385         // go backward for 3 DDU words ( buf2, buf1, and buf0 )
00386         buffer-=12;
00387         buf_1 = &(tmpbuf[0]);  // Just for safety
00388         buf0  = &(tmpbuf[4]);  // Just for safety
00389         buf1  = &(tmpbuf[8]);  // Just for safety
00390         buf2  = &(tmpbuf[12]); // Just for safety
00391         bzero(tmpbuf,sizeof(uint16_t)*16);
00392         sync_stats();
00393         return length+12;
00394       }
00395 
00396 
00397       currentChamber = -1; // Unknown yet
00398 
00399       if( fDDU_Trailer && DDU_WordsSinceLastTrailer != 4 ){
00400         // == Counted extraneous words between last DDU Trailer and this DDU Header
00401         fWARNING[0]=true;
00402         bWARNING|=0x1;
00403         cerr<<"\nDDU Header Occurrence = "<<cntDDU_Headers;
00404         cerr<<"  WARNING 0 "<<sWARNING[0]<<" "<<DDU_WordsSinceLastTrailer<<" extra 64-bit words"<<endl;
00405       }
00406 
00407       sourceID      = ((buf_1[1]&0xF)<<8) | ((buf_1[0]&0xFF00)>>8);
00408       fDDU_Header   = true;
00409       fDDU_Trailer  = false;
00410       DDU_WordCount = 0;
00411       fDMB_Header   = false;
00412       fDMB_Trailer  = false;
00413       fALCT_Header  = false;
00414       fALCT_Format2007= true;
00415       fTMB_Header   = false;
00416       fTMB_Format2007= true;
00417       uniqueALCT    = true;
00418       uniqueTMB     = true;
00419       zeroCounts();
00420 
00421       if (modeDDUonly) {
00422          fDCC_Header  = true;
00423          clear();
00424       }
00425 
00426         dduBuffers[sourceID] = buf_1;
00427         dduOffsets[sourceID] = buf_1-buffer_start;
00428         dduSize   [sourceID] = 0;
00429         dmbBuffers[sourceID].clear();
00430         dmbOffsets[sourceID].clear();
00431         dmbSize   [sourceID].clear();
00432 
00433         // Reset all Error and Warning flags to be false
00434         bDDU_ERR[sourceID] = 0;
00435         bDDU_WRN[sourceID] = 0;
00436         bERROR             = 0;
00437         bWARNING           = 0;
00438         bzero(fERROR,   sizeof(bool)*nERRORS);
00439         bzero(fWARNING, sizeof(bool)*nWARNINGS);
00440 
00441       nDMBs      = 0;
00442       DMB_Active = buf1[0]&0xF;
00443       DAV_DMB    = buf1[1]&0x7FFF;
00444 
00445       int nDAV_DMBs=0;
00446       for(int bit=0; bit<15; bit++) if( DAV_DMB&(1<<bit) ) nDAV_DMBs++;
00447       if(DMB_Active!=nDAV_DMBs){
00448           fERROR[27] = true;
00449           bERROR    |= 0x8000000;
00450       }
00451 
00452       if( (buf_1[3]&0xF000)!=0x5000 ){
00453         fWARNING[1]=true;
00454         bWARNING|=0x2;
00455         cerr<<"\nDDU Header Occurrence = "<<cntDDU_Headers;
00456                 cerr<<"  WARNING 1 "<<sWARNING[1]<<". What must have been Header 1: 0x"<<std::hex<<buf_1[0]<<" 0x"<<buf_1[1]<<" 0x"<<buf_1[2]<<" 0x"<<buf_1[3]<<std::dec<<endl;
00457       }
00458 
00459       ++cntDDU_Headers;
00460       DDU_WordsSinceLastHeader=0; // Reset counter of DDU Words since last DDU Header
00461       cout<<"\n----------------------------------------------------------"<<endl;
00462       cout<<"DDU  Header Occurrence "<<cntDDU_Headers<< " L1A = " << ( ((buf_1[2]&0xFFFF) + ((buf_1[3]&0x00FF) << 16)) ) <<endl;
00463     }
00464 
00465     // == DMB Header found
00466     if( (buf0[0]&0xF000)==0xA000 && (buf0[1]&0xF000)==0xA000 && (buf0[2]&0xF000)==0xA000 && (buf0[3]&0xF000)==0xA000 ){
00468       checkDAVs();
00469       checkTriggerHeadersAndTrailers();
00471 
00472       if( DDU_WordsSinceLastHeader>3 && !fDMB_Header && !fDMB_Trailer && !nDMBs ){
00473         fERROR[28]=true;
00474         bERROR|=0x10000000;;
00475       }
00476 
00477       if( fDMB_Header || fDMB_Trailer ){ // F or E  DMB Trailer is missed
00478         fERROR[5]=true;
00479         bERROR|=0x20;
00480         fCHAMB_ERR[5].insert(currentChamber);
00481         bCHAMB_ERR[currentChamber] |= 0x20;
00482         fCHAMB_ERR[0].insert(currentChamber);
00483         bCHAMB_ERR[currentChamber] |= 0x1;
00484       }
00485       fDMB_Header  = true;
00486       fDMB_Trailer = false;
00487 
00488       // If previous DMB record was not assigned to any chamber ( it still has -1 indentificator )
00489       // let's free -1 identificator for current use and call undefined chamber from previous record -2
00490       // ( -2 may already exists in this sets but we have nothing to do with it )
00491       for(int err=0; err<nERRORS; ++err)
00492         if( fCHAMB_ERR[err].find(-1) != fCHAMB_ERR[err].end() ){
00493           fCHAMB_ERR[err].erase(-1);
00494           fCHAMB_ERR[err].insert(-2);
00495         }
00496 // Two lines below are commented out because payloads never get filled if 0xA header is missing
00497 //      bCHAMB_PAYLOAD[-2] |= bCHAMB_PAYLOAD[-1];
00498 //      fCHAMB_PAYLOAD[-1] = 0;
00499       bCHAMB_STATUS[-2] |= bCHAMB_STATUS[-1];
00500       bCHAMB_STATUS[-1] = 0;
00501       bCHAMB_ERR[-2] |= bCHAMB_ERR[-1];
00502       bCHAMB_ERR[-1] = 0;
00503       bCHAMB_WRN[-2] |= bCHAMB_WRN[-1];
00504       bCHAMB_WRN[-1] = 0;
00505 
00506       // Chamber id ( DMB_ID + (DMB_CRATE<<4) ) from header
00507       currentChamber = buf0[1]&0x0FFF;
00508       ++cntCHAMB_Headers[currentChamber];
00509       bCHAMB_ERR[currentChamber] |= 0; //Victor's line
00510 
00511       fALCT_Header = false;
00512       fALCT_Format2007= true;
00513       fTMB_Header  = false;
00514       fTMB_Format2007= true;
00515       uniqueALCT   = true;
00516       uniqueTMB    = true;
00517 
00518       fTMB_Scope_Start = false;
00519       fTMB_MiniScope_Start = false;
00520       fTMB_RPC_Start = false;
00521       fTMB_BlockedCFEBs_Start = false;
00522 
00523       fTMB_Scope = false;
00524       fTMB_MiniScope = false;
00525       fTMB_RPC = false;
00526       fTMB_BlockedCFEBs = false;       
00527 
00528 
00529       zeroCounts();
00530       CFEB_CRC                  = 0;
00531 
00532       nDMBs++;
00533 
00534       dmbBuffers[sourceID][currentChamber] = buf0-4;
00535       dmbOffsets[sourceID][currentChamber] = buf0-4-buffer_start;
00536       dmbSize   [sourceID][currentChamber] = 4;
00537 
00538       // Print DMB_ID from DMB Header
00539       cout<< "Crate=" << setw(3) << setfill('0') << ((buf0[1]>>4)&0x00FF) << " DMB="<<setw(2)<<setfill('0')<<(buf0[1]&0x000F)<<" ";
00540       // Print ALCT_DAV and TMB_DAV from DMB Header
00541       //cout<<setw(1)<<((buf0[0]&0x0020)>>5)<<" "<<((buf0[0]&0x0040)>>6)<<" ";
00542       cout<<setw(1)<<((buf0[0]&0x0200)>>9)<<" "<<((buf0[0]&0x0800)>>11)<<" "; //change of format 16.09.05
00543       // Print CFEB_DAV from DMB Header
00544       cout<<setw(1)<<((buf0[0]&0x0010)>>4)<<((buf0[0]&0x0008)>>3)<<((buf0[0]&0x0004)>>2)<<((buf0[0]&0x0002)>>1)<<(buf0[0]&0x0001);
00545       // Print DMB Header Tag
00546       cout << " {";
00547 
00548       // Set variables if we are waiting ALCT, TMB and CFEB records to be present in event
00549       DAV_ALCT = (buf0[0]&0x0200)>>9;
00550       DAV_TMB  = (buf0[0]&0x0800)>>11;
00551       DAV_CFEB = 0;
00552       if( buf0[0]&0x0001 ) ++DAV_CFEB;
00553       if( buf0[0]&0x0002 ) ++DAV_CFEB;
00554       if( buf0[0]&0x0004 ) ++DAV_CFEB;
00555       if( buf0[0]&0x0008 ) ++DAV_CFEB;
00556       if( buf0[0]&0x0010 ) ++DAV_CFEB;
00557       if( DAV_ALCT ) bCHAMB_PAYLOAD[currentChamber] |= 0x20;
00558       if( DAV_TMB  ) bCHAMB_PAYLOAD[currentChamber] |= 0x40;
00559       bCHAMB_PAYLOAD[currentChamber] |= (buf0[0]&0x001f)<<7;
00560       bCHAMB_PAYLOAD[currentChamber] |=((buf_1[2]>>5)&0x001f);
00561           bCHAMB_STATUS [currentChamber] |= (buf0[0]&0x0040)<<16;
00562     }
00563 
00564 
00565     // New ALCT data format:
00566     if( ( buf0[0]==0xDB0A && (buf0[1]&0xF000)==0xD000 && (buf0[2]&0xF000)==0xD000 && (buf0[3]&0xF000)==0xD000)
00567         &&
00568         ( (buf_1[0]&0xF000)==0xA000 && (buf_1[1]&0xF000)==0xA000 && (buf_1[2]&0xF000)==0xA000 && (buf_1[3]&0xF000)==0xA000 ) ){
00569         fALCT_Header              = true;
00570         fALCT_Format2007          = true;
00571         ALCT_CRC                  = 0;
00572         ALCT_WordsSinceLastHeader = 4;
00573         ALCT_WordsSinceLastHeaderZeroSuppressed = 4;
00574 
00575         // Calculate expected number of ALCT words
00576         ALCT_WordsExpected = 12; // header and trailer always exists
00577 
00578         //  Aauxilary variables
00579         //   number of wire groups per layer:
00580         int  nWGs_per_layer = ( (buf1[2]&0x0007) + 1 ) * 16 ;
00581         // words in the layer
00582         nWG_round_up   = int(nWGs_per_layer/12)+(nWGs_per_layer%3?1:0);
00583         //   configuration present:
00584         bool config_present =  buf1[0]&0x4000;
00585         //   lct overflow:
00586         bool lct_overflow   =  buf1[0]&0x2000;
00587         //   raw overflow:
00588         bool raw_overflow   =  buf1[0]&0x1000;
00589         //   l1a_window:
00590         int  lct_tbins      = (buf1[3]&0x01E0)>>5;
00591         //   fifo_tbins:
00592         int  raw_tbins      = (buf1[3]&0x001F);
00593         
00595         ALCT_ZSE            = (buf1[1]&0x1000)>>12;
00596         
00597         if (ALCT_ZSE)
00598             {
00599               for (int g=0; g<4; g++)
00600                 {
00601                   if (buf1[g]==0x1000) ALCT_WordsSinceLastHeader -= (nWG_round_up - 1);
00602                 }
00603             }
00604 
00605 //        std::cout << " Number of Wire Groups: " << nWG_round_up << std::endl;
00607 //        std::cout << " raw_tbins: " << std::dec << raw_tbins << std::endl;
00608 //        std::cout << " LCT Tbins: " << lct_tbins << std::endl;        
00609 
00610         //  Data block sizes:
00611         //   3 words of Vertex ID register + 5 words of config. register bits:
00612         int config_size    = ( config_present ? 3 + 5 : 0 );
00613         //   collision mask register:
00614         int colreg_size    = ( config_present ? nWGs_per_layer/4 : 0 );
00615         //   hot channel mask:
00616         int hot_ch_size    = ( config_present ? nWG_round_up*6 : 0 );
00617         //   ALCT0,1 (best tracks):
00618         int alct_0_1_size  = ( !lct_overflow ? 2*lct_tbins : 0 );
00619         //   raw hit dump size:
00620         int raw_hit_dump_size=(!raw_overflow ? nWG_round_up*6*raw_tbins : 0 );
00621 
00622         //std::cout << " Raw Hit Dump: " << std::dec << raw_hit_dump_size << std::endl;
00623 
00624         ALCT_WordsExpected += config_size + colreg_size + hot_ch_size + alct_0_1_size + raw_hit_dump_size;
00625 
00626         cout<<" <A";
00627     } else {
00628         // Old ALCT data format
00629 
00630         // == ALCT Header found right after DMB Header
00631         //   (check for all currently reserved/fixed bits in ALCT first 4 words)
00632         // if( ( (buf0 [0]&0xF800)==0x6000 && (buf0 [1]&0xFF80)==0x0080 && (buf0 [2]&0xF000)==0x0000 && (buf0 [3]&0xc000)==0x0000 )
00633         if( ( (buf0 [0]&0xF800)==0x6000 && (buf0 [1]&0x8F80)==0x0080 && (buf0 [2]&0x8000)==0x0000 && (buf0 [3]&0xc000)==0x0000 )
00634             &&
00635             ( (buf_1[0]&0xF000)==0xA000 && (buf_1[1]&0xF000)==0xA000 && (buf_1[2]&0xF000)==0xA000 && (buf_1[3]&0xF000)==0xA000 ) ){
00636               fALCT_Header              = true;
00637               fALCT_Format2007          = false;
00638               ALCT_CRC                  = 0;
00639               ALCT_WordsSinceLastHeader = 4;
00640 
00641               // Calculate expected number of ALCT words
00642               if( (buf0[3]&0x0003)==0 ){ ALCT_WordsExpected = 12; }     // Short Readout
00643 
00644               if( (buf0[1]&0x0003)==1 ){                                        // Full Readout
00645                        ALCT_WordsExpected = ((buf0[1]&0x007c) >> 2) *
00646                         ( ((buf0[3]&0x0001)   )+((buf0[3]&0x0002)>>1)+
00647                         ((buf0[3]&0x0004)>>2)+((buf0[3]&0x0008)>>3)+
00648                         ((buf0[3]&0x0010)>>4)+((buf0[3]&0x0020)>>5)+
00649                         ((buf0[3]&0x0040)>>6) ) * 12 + 12;
00650               }
00651               cout<<" <A";
00652         }
00653     }
00654     //std::cout << " ALCT Word Expected: " << ALCT_WordsExpected << std::endl;
00655 
00656     if( (buf0[0]&0xFFFF)==0xDB0C ){
00657         fTMB_Header              = true;
00658         fTMB_Format2007          = true;
00659         TMB_CRC                  = 0;
00660         TMB_WordsSinceLastHeader = 4;
00661         TMB_WordsExpected = 0;
00662 
00663         // Calculate expected number of TMB words (whether RPC included will be known later)
00664         if ( (buf1[1]&0x3000) == 0x3000) { TMB_WordsExpected = 12; }  // Short Header Only
00665         if ( (buf1[1]&0x3000) == 0x0000) { TMB_WordsExpected = 48; }  // Long Header Only
00666 
00667         cout << " <T";
00668     } else {
00669         // == TMB Header found right after DMB Header or right after ALCT Trailer
00670         if(   (buf0 [0]&0xFFFF)==0x6B0C && (
00671                                         ( (buf_1[0]&0xF000)==0xA000 && (buf_1[1]&0xF000)==0xA000 && (buf_1[2]&0xF000)==0xA000 && (buf_1[3]&0xF000)==0xA000 )
00672                                         ||
00673                                         ( (buf_1[0]&0x0800)==0x0000 && (buf_1[1]&0xF800)==0xD000 && (buf_1[2]&0xFFFF)==0xDE0D && (buf_1[3]&0xF000)==0xD000 )
00674                                         // should've been (buf_1[0]&0xF800)==0xD000 - see comments for sERROR[11]
00675                                         ) )
00676         {
00677         //if( (buf_1[2]&0xFFFF)==0xDE0D && (buf_1[3]&0xFC00)!=0xD000 && summer2004 ) ???
00678 
00679             fTMB_Header              = true;
00680             fTMB_Format2007          = false;
00681             TMB_CRC                  = 0;
00682             TMB_WordsSinceLastHeader = 4;
00683 
00684             // Calculate expected number of TMB words (whether RPC included will be known later)
00685             if ( (buf0[1]&0x3000) == 0x3000) { TMB_WordsExpected = 8; }   // Short Header Only
00686             if ( (buf0[1]&0x3000) == 0x0000) { TMB_WordsExpected = 32; }  // Long Header Only
00687 
00688             if ( (buf0[1]&0x3000) == 0x1000) {
00689                 // Full Readout   = 28 + (#Tbins * #CFEBs * 6)
00690                 TMB_Tbins=(buf0[1]&0x001F);
00691                 TMB_WordsExpected = 28 + TMB_Tbins * ((buf1[0]&0x00E0)>>5) * 6;
00692             }
00693 
00694                         cout << " <T";
00695                 }
00696         }
00697     // New TMB format => very long header Find Firmware revision
00698     if ( fTMB_Header && fTMB_Format2007 && TMB_WordsSinceLastHeader==8 ) {
00699         TMB_Firmware_Revision = buf0[3];
00700     }
00701 
00702     // New TMB format => very long header
00703     if ( fTMB_Header && fTMB_Format2007 && TMB_WordsSinceLastHeader==20 ) {
00704         // Full Readout   = 44 + (#Tbins * #CFEBs * 6)
00705         TMB_Tbins=(buf0[3]&0x00F8)>>3;
00706         TMB_WordsExpected = 44 + TMB_Tbins * (buf0[3]&0x0007) * 6;
00707     }
00708 
00709     // == ALCT Trailer found
00710         if(
00711         // New ALCT data format:
00712         ( buf0[0]==0xDE0D && (buf0[1]&0xF800)==0xD000 && (buf0[2]&0xF800)==0xD000 && (buf0[3]&0xF000)==0xD000 && fALCT_Format2007 ) ||
00713         // Old ALCT data format; last check is added to avoid confusion with new TMB header (may not be needed):
00714         ( (buf0[0]&0x0800)==0x0000 && (buf0[1]&0xF800)==0xD000 && (buf0[2]&0xFFFF)==0xDE0D && (buf0[3]&0xF000)==0xD000 && !fALCT_Format2007 && !(fTMB_Header&&fTMB_Format2007) )
00715     ){
00716       // should've been (buf0[0]&0xF800)==0xD000 - see comments for sERROR[11]
00717 
00718       // Second ALCT -> Lost both previous DMB Trailer and current DMB Header
00719       if( !uniqueALCT ) currentChamber = -1;
00720       // Check if this ALCT record have to exist according to DMB Header
00721       if(   DAV_ALCT  ) DAV_ALCT = false; else DAV_ALCT = true;
00722 
00723       if( !fALCT_Header ){
00724         fERROR[8] = true;
00725         bERROR   |= 0x100;
00726         fCHAMB_ERR[8].insert(currentChamber);
00727         bCHAMB_ERR[currentChamber] |= 0x100;
00728         fCHAMB_ERR[0].insert(currentChamber);
00729         bCHAMB_ERR[currentChamber] |= 0x1;
00730       } // ALCT Header is missing
00731 
00732       if( !fALCT_Format2007 && (buf0[0]&0xF800)!=0xD000 ){
00733         fERROR[11] = true;
00734         bERROR    |= 0x800;
00735         fCHAMB_ERR[11].insert(currentChamber);
00736         bCHAMB_ERR[currentChamber] |= 0x800;
00737         fCHAMB_ERR[0].insert(currentChamber);
00738         bCHAMB_ERR[currentChamber] |= 0x1;
00739       } // some bits in 1st D-Trailer are lost
00740 
00742 /*
00743       std::cout << " ALCT Word Since Last Header: " << ALCT_WordsSinceLastHeader << std::endl;
00744       std::cout << " ALCT Word Expected: " << ALCT_WordsExpected << std::endl;
00745       std::cout << " ALCT Word Since Last Header Zero Supressed: " << ALCT_WordsSinceLastHeaderZeroSuppressed <<
00746       std::endl;
00747 */
00749       if( checkCrcALCT ){
00750     uint32_t crc = ( fALCT_Format2007 ? buf0[1] : buf0[0] ) & 0x7ff;
00751     crc |= ((uint32_t)( ( fALCT_Format2007 ? buf0[2] : buf0[1] ) & 0x7ff)) << 11;
00752         if( ALCT_CRC != crc ){
00753           fERROR[10] = true;
00754           bERROR   |= 0x400;
00755           fCHAMB_ERR[10].insert(currentChamber);
00756           bCHAMB_ERR[currentChamber] |= 0x400;
00757           fCHAMB_ERR[0].insert(currentChamber);
00758           bCHAMB_ERR[currentChamber] |= 0x1;
00759         }
00760       }
00761 
00762       fALCT_Header = false;
00763       uniqueALCT   = false;
00764       CFEB_CRC     = 0;
00765       //ALCT_WordCount = (buf0[3]&0x03FF);
00766       ALCT_WordCount = (buf0[3]&0x07FF);
00767       //ALCT_WordCount = (buf0[3]&0x0FFF);
00768       CFEB_SampleWordCount = 0;
00769       cout << "A> ";
00770     }
00771 
00772     // Calculation of CRC sum ( algorithm is written by Madorsky )
00773     if( fALCT_Header && checkCrcALCT ){
00774       for(uint16_t j=0, w=0; j<4; ++j){
00776         w = buf0[j] & (fALCT_Format2007 ? 0xffff : 0x7fff);
00777         for(uint32_t i=15, t=0, ncrc=0; i<16; i--){
00778           t = ((w >> i) & 1) ^ ((ALCT_CRC >> 21) & 1);
00779           ncrc = (ALCT_CRC << 1) & 0x3ffffc;
00780           ncrc |= (t ^ (ALCT_CRC & 1)) << 1;
00781           ncrc |= t;
00782           ALCT_CRC = ncrc;
00783         }
00784       }
00785     }
00786 
00787     // == Find Correction for TMB_WordsExpected due to RPC raw hits,
00788     //    should it turn out to be the new RPC-aware format
00789     if( fTMB_Header && ((buf0[2]&0xFFFF)==0x6E0B) )  {
00790       if (fTMB_Format2007) {
00791         if (TMB_Firmware_Revision >= 0x50c3) { // TMB2007 rev.0x50c3
00792           // On/off * nRPCs * nTimebins * 2 words/RPC/bin
00793           TMB_WordsRPC = ((buf_1[0]&0x0010)>>4) * ((buf_1[0]&0x000c)>>2) * ((buf_1[0]>>5) & 0x1F) * 2;
00794         }
00795         else { // TMB2007 (may not work since TMB_Tbins != RPC_Tbins)
00796           TMB_WordsRPC = ((buf_1[0]&0x0040)>>6) * ((buf_1[0]&0x0030)>>4) * TMB_Tbins * 2;
00797         }
00798       }
00799       else { // Old format
00800         TMB_WordsRPC   = ((buf_1[2]&0x0040)>>6) * ((buf_1[2]&0x0030)>>4) * TMB_Tbins * 2;
00801       }
00802       TMB_WordsRPC += 2; // add header/trailer for block of RPC raw hits
00803     }
00804 
00805 
00806         
00807     // Check for RPC data
00808     if ( fTMB_Header && (scanbuf(buf0,4, 0x6B04)>=0) ) {
00809         fTMB_RPC_Start = true;
00810       }
00811 
00812     // Check for Scope data
00813     if ( fTMB_Header && (scanbuf(buf0,4, 0x6B05)>=0) ) { 
00814         fTMB_Scope_Start = true;
00815       }
00816 
00817     // Check for Mini-Scope data
00818     if ( fTMB_Header && (scanbuf(buf0,4, 0x6B07)>=0) ) { 
00819         fTMB_MiniScope_Start = true;
00820       }
00821     
00822     // Check for Blocked CFEBs data
00823     if ( fTMB_Header && (scanbuf(buf0,4, 0x6BCB)>=0) ) { 
00824         fTMB_BlockedCFEBs_Start = true;
00825       }
00826 
00827     
00828     // Check for end of RPC data
00829     if ( fTMB_Header && fTMB_RPC_Start 
00830         && (scanbuf(buf0,4, 0x6E04)>=0) ) {
00831         fTMB_RPC = true;
00832       }
00833 
00834     // Check for end of Scope data
00835     if ( fTMB_Header && fTMB_Scope_Start 
00836         && (scanbuf(buf0,4, 0x6E05)>=0) ) {
00837         fTMB_Scope = true;
00838       }
00839 
00840     // Check for end of Mini-Scope data
00841     if ( fTMB_Header && fTMB_MiniScope_Start 
00842         && (scanbuf(buf0,4, 0x6E07)>=0) ) {
00843         fTMB_MiniScope = true;
00844       }
00845 
00846     // Check for end of Blocked CFEBs data
00847     if ( fTMB_Header && fTMB_BlockedCFEBs_Start 
00848         && (scanbuf(buf0,4, 0x6ECB)>=0) ) {
00849         fTMB_BlockedCFEBs = true;
00850       }
00851 
00852  /* 
00853     if ( fTMB_Header && (scanbuf(buf0,4, 0x6E04)>=0) ) {
00854           TMB_WordsExpected += TMB_WordsRPC; 
00855       }
00856 */
00857 
00858     // == TMB Trailer found
00859     if(
00860        // Old TMB data format; last condition in needed not to confuse if with new ALCT data header
00861        ((buf0[0]&0xF000)==0xD000 && (buf0[1]&0xF000)==0xD000 && (buf0[2]&0xFFFF)==0xDE0F && (buf0[3]&0xF000)==0xD000 && !fTMB_Format2007 && !(fALCT_Header&&fALCT_Format2007)) ||
00862        // New TMB data format
00863        ( buf0[0]==        0xDE0F && (buf0[1]&0xF000)==0xD000 && (buf0[2]&0xF000)==0xD000 && (buf0[3]&0xF000)==0xD000 &&  fTMB_Format2007 )
00864     ){
00865 
00866       // Second TMB -> Lost both previous DMB Trailer and current DMB Header
00867       if( !uniqueTMB ) currentChamber = -1;
00868       // Check if this TMB record have to exist according to DMB Header
00869       if(   DAV_TMB  ) DAV_TMB = false; else DAV_TMB = true;
00870 
00871       if(!fTMB_Header){
00872         fERROR[13] = true;
00873         bERROR    |= 0x2000;
00874         fCHAMB_ERR[13].insert(currentChamber);
00875         bCHAMB_ERR[currentChamber] |= 0x2000;
00876         fCHAMB_ERR[0].insert(currentChamber);
00877         bCHAMB_ERR[currentChamber] |= 0x1;
00878       }  // TMB Header is missing
00879 
00880       // Check calculated CRC sum against reported
00881       if( checkCrcTMB ){
00882     uint32_t crc = ( fTMB_Format2007 ? buf0[1]&0x7ff : buf0[0]&0x7ff );
00883     crc |= ((uint32_t)( ( fTMB_Format2007 ? buf0[2]&0x7ff : buf0[1] & 0x7ff ) )) << 11;
00884         if( TMB_CRC != crc ){
00885           fERROR[15] = true;
00886           bERROR    |= 0x8000;
00887           fCHAMB_ERR[15].insert(currentChamber);
00888           bCHAMB_ERR[currentChamber] |= 0x8000;
00889           fCHAMB_ERR[0].insert(currentChamber);
00890           bCHAMB_ERR[currentChamber] |= 0x1;
00891         }
00892       }
00893 
00894       fTMB_Header = false;
00895       uniqueTMB   = false;
00896       CFEB_CRC     = 0;
00897       TMB_WordCount = (buf0[3]&0x07FF);
00898 
00899       // == Correct TMB_WordsExpected
00900       //        1) for 2 optional 0x2AAA and 0x5555 Words in the Trailer
00901       //        2) for extra 4 frames in the new TMB trailer and
00902       //         for RPC raw hit data, if present
00903       //
00904       // If the scope data was enabled in readout, scope data markers (0x6B05
00905       // and 0x6E05) appear before 0x6E0C, and the optional 0x2AAA and 0x5555
00906       // trailer words are suppressed.  So far, we only have data with the
00907       // empty scope content, so more corrections will be needed once
00908       // non-empty scope data is available. -SV, 5 Nov 2008.
00909       //
00910       // If word count is not multiple of 4, add 2 optional words and
00911       // 4 trailer words.
00912   
00913       int pos = scanbuf(buf_1,4,0x6E0C);
00914       if (pos==1) {
00915         TMB_WordsExpected += 6;
00916       }
00917       // If word count is multiple of 4, add 4 trailer words.
00918       else if (pos==3) {
00919         TMB_WordsExpected += 4;
00920       }
00921 
00922       // Correct expected wordcount by RPC data size
00923       if (fTMB_RPC) 
00924         TMB_WordsExpected += TMB_WordsRPC;
00925 
00926       // Correct expected wordcount by MiniScope data size (22 words + 2 signature words)
00927       if (fTMB_MiniScope) 
00928         TMB_WordsExpected += 24;
00929 
00930       // Correct expected wordcount by BlockedCFEBs data size (20 words + 2 signature words) 
00931       if (fTMB_BlockedCFEBs) 
00932         TMB_WordsExpected += 22;
00933 
00934       CFEB_SampleWordCount = 0;
00935       cout << "T> ";
00936     }
00937 
00938     if( fTMB_Header && checkCrcTMB ){
00939       for(uint16_t j=0, w=0; j<4; ++j){
00941         w = buf0[j] & (fTMB_Format2007 ? 0xffff : 0x7fff);
00942         for(uint32_t i=15, t=0, ncrc=0; i<16; i--){
00943           t = ((w >> i) & 1) ^ ((TMB_CRC >> 21) & 1);
00944           ncrc = (TMB_CRC << 1) & 0x3ffffc;
00945           ncrc |= (t ^ (TMB_CRC & 1)) << 1;
00946           ncrc |= t;
00947           TMB_CRC = ncrc;
00948         }
00949       }
00950     }
00951 
00952 
00953     // == CFEB Sample Trailer found
00954 
00955         if( ((buf0[1]&0xF000)==0x7000) &&
00956                 ((buf0[2]&0xF000)==0x7000) &&
00957                 ((buf0[1]!=0x7FFF) || (buf0[2]!=0x7FFF)) &&
00958                 ( ((buf0[3]&0xFFFF)==0x7FFF) ||   // old format
00959               ( (buf0[3]&buf0[0])==0x0000 && (buf0[3]+buf0[0])==0x7FFF ) // 2007 format
00960               ) ){
00961 
00962       if((CFEB_SampleCount%8)  == 0   ){ cout<<" <"; }
00963       if( CFEB_SampleWordCount == 100 ){ cout<<"+";  }
00964       if( CFEB_SampleWordCount != 100 ){ cout<<"-";
00965       fERROR[16] = true;
00966       bERROR    |= 0x10000;
00967       fCHAMB_ERR[16].insert(currentChamber);
00968       bCHAMB_ERR[currentChamber] |= 0x10000;
00969       fCHAMB_ERR[0].insert(currentChamber);
00970       bCHAMB_ERR[currentChamber] |= 0x1;
00971       }
00972 
00973       ++CFEB_SampleCount;
00974 
00975       if( (CFEB_SampleCount%8)==0 ){
00976         cout<<">";
00977         CFEB_BSampleCount=0;
00978         // Count CFEBs
00979         DAV_CFEB--;
00980       }
00981 
00982       // Check calculated CRC sum against reported
00983       if( checkCrcCFEB && CFEB_CRC!=buf0[0] ){
00984         fERROR[18] = true;
00985         bERROR    |= 0x40000;
00986         fCHAMB_ERR[18].insert(currentChamber);
00987         bCHAMB_ERR[currentChamber] |= 0x40000;
00988         fCHAMB_ERR[0].insert(currentChamber);
00989         bCHAMB_ERR[currentChamber] |= 0x1;
00990       }
00991 
00992       CFEB_CRC = 0;
00993       CFEB_SampleWordCount=0;
00994     }
00995 
00996 
00997     // == CFEB B-word found
00998     if( (buf0[0]&0xF000)==0xB000 && (buf0[1]&0xF000)==0xB000 && (buf0[2]&0xF000)==0xB000 && (buf0[3]&0xF000)==0xB000 ){
00999       bCHAMB_STATUS[currentChamber] |= 0x400000;
01000 
01001       if( (CFEB_SampleCount%8)==0 ){ cout<<" <"; }
01002       cout<<"B";
01003 
01004       ++CFEB_SampleCount;
01005       ++CFEB_BSampleCount;
01006 
01007       if( (CFEB_SampleCount%8)==0 ){
01008         cout << ">";
01009         CFEB_BSampleCount=0;
01010         DAV_CFEB--;
01011       }
01012 
01013       CFEB_SampleWordCount=0;
01014     }
01015 
01016      // == If it is neither ALCT record nor TMB - probably it is CFEB record and we try to count CRC sum.
01017     // It very few words of CFEB occasionaly will be misinterpreted as ALCT or TMB header the result
01018     // for the CRC sum will be wrong, but other errors of Trailers counting will appear as well
01019     if( checkCrcCFEB && fDMB_Header && !fTMB_Header && !fALCT_Header && CFEB_SampleWordCount )
01020       for(int pos=0; pos<4; ++pos)
01021         CFEB_CRC=(buf0[pos]&0x1fff)^((buf0[pos]&0x1fff)<<1)^(((CFEB_CRC&0x7ffc)>>2)|((0x0003&CFEB_CRC)<<13))^((CFEB_CRC&0x7ffc)>>1);
01022 
01023 
01024     // == DMB F-Trailer found
01025     if( (buf0[0]&0xF000)==0xF000 && (buf0[1]&0xF000)==0xF000 && (buf0[2]&0xF000)==0xF000 && (buf0[3]&0xF000)==0xF000 ){
01026       if(!fDMB_Header){
01027         currentChamber = buf0[3]&0x0FFF;
01028         fERROR[6] = true;
01029         bERROR   |= 0x40;
01030         fCHAMB_ERR[6].insert(currentChamber);
01031         bCHAMB_ERR[currentChamber] |= 0x40;
01032         nDMBs++;
01033         // Set variables if we are waiting ALCT, TMB and CFEB records to be present in event
01034         if( buf0[0]&0x0400 ) bCHAMB_PAYLOAD[currentChamber] |= 0x20;
01035         if( buf0[0]&0x0800 ) bCHAMB_PAYLOAD[currentChamber] |= 0x40;
01036         bCHAMB_PAYLOAD[currentChamber] |= (buf0[0]&0x001f)<<7;
01037         bCHAMB_PAYLOAD[currentChamber] |=((buf0[0]>>5)&0x1f);
01038 
01039       } // DMB Header is missing
01040       fDMB_Header  = false;
01041       fDMB_Trailer = true;
01042       uniqueALCT   = true;
01043       uniqueTMB    = true;
01044 
01045       dmbSize[sourceID][currentChamber] = buf0 - dmbBuffers[sourceID][currentChamber];
01046 
01047       // Finally check if DAVs were correct
01048       checkDAVs();
01049 
01050       // If F-Trailer is lost then do necessary work here
01051       if( (buf1[0]&0xF000)!=0xE000 || (buf1[1]&0xF000)!=0xE000 || (buf1[2]&0xF000)!=0xE000 || (buf1[3]&0xF000)!=0xE000 ){
01052         for(int err=1; err<nERRORS; ++err)
01053           if( fCHAMB_ERR[err].find(currentChamber) != fCHAMB_ERR[err].end() ){
01054             fCHAMB_ERR[0].insert(currentChamber);
01055             bCHAMB_ERR[currentChamber] |= 0x1;
01056           }
01057         // Reset chamber id
01058         currentChamber=-1;
01059         /*
01060           for(int err=0; err<nERRORS; err++)
01061           if( fCHAMB_ERR[err].find(-1) != fCHAMB_ERR[err].end() )
01062           fCHAMB_ERR[err].erase(-1);
01063           bCHAMB_ERR[-1] = 0;
01064           bCHAMB_WRN[-1] = 0;
01065         */
01066       }
01067 
01068       // Print DMB F-Trailer marker
01069       cout << " }";
01070     }
01071 
01072     // == DMB E-Trailer found
01073     if( (buf0[0]&0xF000)==0xE000 && (buf0[1]&0xF000)==0xE000 && (buf0[2]&0xF000)==0xE000 && (buf0[3]&0xF000)==0xE000 ){
01074       if( !fDMB_Header && !fDMB_Trailer ) nDMBs++; // both DMB Header and DMB F-Trailer were missing
01075 
01076       bCHAMB_STATUS[currentChamber] |= (buf0[0]&0x0800)>>11;
01077       bCHAMB_STATUS[currentChamber] |= (buf0[0]&0x0400)>>9;
01078       bCHAMB_STATUS[currentChamber] |= (buf0[0]&0x03E0)>>3;
01079       if( fDMB_Trailer ){ // F-Trailer exists
01080         bCHAMB_STATUS[currentChamber] |= (buf_1[2]&0x0002)<<6;
01081         bCHAMB_STATUS[currentChamber] |= (buf_1[2]&0x0001)<<8;
01082         bCHAMB_STATUS[currentChamber] |= (buf_1[3]&0x001f)<<9;
01083         bCHAMB_STATUS[currentChamber] |= (buf_1[3]&0x0040)<<8;
01084         bCHAMB_STATUS[currentChamber] |= (buf_1[3]&0x0020)<<10;
01085                 bCHAMB_STATUS[currentChamber] |= (buf_1[3]&0x0f80)<<9;
01086       }
01087       fDMB_Header  = false;
01088 
01089       // If chamber id is unknown it is time to find it out
01090       if( currentChamber==-1 ){
01091         currentChamber = buf0[1]&0x0FFF;
01092         for(int err=0; err<nERRORS; ++err)
01093           if( fCHAMB_ERR[err].find(-1) != fCHAMB_ERR[err].end() ){
01094             fCHAMB_ERR[err].insert(currentChamber);
01095             fCHAMB_ERR[err].erase(-1);
01096           }
01097     bCHAMB_STATUS[currentChamber] = bCHAMB_STATUS[-1];
01098     bCHAMB_STATUS[-1] = 0;
01099         bCHAMB_ERR[currentChamber] = bCHAMB_ERR[-1];
01100         bCHAMB_ERR[-1] = 0;
01101         bCHAMB_WRN[currentChamber] = bCHAMB_WRN[-1];
01102         bCHAMB_WRN[-1] = 0;
01103       }
01104       ++cntCHAMB_Trailers[buf0[1]&0x0FFF];
01105 
01106       dmbSize[sourceID][currentChamber] = buf0 - dmbBuffers[sourceID][currentChamber];
01107 
01108       // Lost DMB F-Trailer before
01109       if( !fDMB_Trailer ){
01110         fERROR[6] = true;
01111         bERROR   |= 0x40;
01112         fCHAMB_ERR[6].insert(currentChamber);
01113         bCHAMB_ERR[currentChamber] |= 0x40;
01114         fCHAMB_ERR[0].insert(currentChamber);
01115         bCHAMB_ERR[currentChamber] |= 0x1;
01116         // Check if DAVs were correct here
01117         checkDAVs();
01118       }
01119       fDMB_Trailer = false;
01120 
01121      // Print DMB E-Trailer marker
01122       cout<<" DMB="<<(buf0[1]&0x000F);
01123       cout << "; "
01124            << ALCT_WordsSinceLastHeader << "-"
01125            << ALCT_WordCount << "-"
01126            << ALCT_WordsExpected
01127            << "      "
01128            << TMB_WordsSinceLastHeader << "-"
01129            << TMB_WordCount << "-"
01130            << TMB_WordsExpected
01131            << endl;
01132 
01133      checkTriggerHeadersAndTrailers();
01134 
01135       //
01136       for(int err=0; err<nERRORS; ++err)
01137         if( fCHAMB_ERR[err].find(-1) != fCHAMB_ERR[err].end() ){
01138           fCHAMB_ERR[err].erase(-1);
01139           fCHAMB_ERR[err].insert(-2);
01140         }
01141       bCHAMB_STATUS[-2] |= bCHAMB_STATUS[-1];
01142       bCHAMB_STATUS[-1] = 0;
01143       bCHAMB_ERR[-2] |= bCHAMB_ERR[-1];
01144       bCHAMB_ERR[-1] = 0;
01145       bCHAMB_WRN[-2] |= bCHAMB_WRN[-1];
01146       bCHAMB_WRN[-1] = 0;
01147 
01148       if( currentChamber != -1 )
01149         for(int err=1; err<nERRORS; ++err)
01150           if( fCHAMB_ERR[err].find(currentChamber) != fCHAMB_ERR[err].end() ){
01151             fCHAMB_ERR[0].insert(currentChamber);
01152             bCHAMB_ERR[currentChamber] |= 0x1;
01153           }
01154 
01155       currentChamber=-1;
01156 /*
01157       // Print DMB E-Trailer marker
01158       cout<<" DMB="<<(buf0[1]&0x000F);
01159       cout << "; "
01160            << ALCT_WordsSinceLastHeader << "-"
01161            << ALCT_WordCount << "-"
01162            << ALCT_WordsExpected
01163            << "      "
01164            << TMB_WordsSinceLastHeader << "-"
01165            << TMB_WordCount << "-"
01166            << TMB_WordsExpected
01167            << endl;
01168 */
01169 
01170     }
01171 
01172     // == DDU Trailer found
01173     if( buf0[0]==0x8000 && buf0[1]==0x8000 && buf0[2]==0xFFFF && buf0[3]==0x8000 ){
01174       // Obsolete since 16.09.05
01175       //                        if( headerDAV_Active != ((buf1[1]<<16) | buf1[0]) ){
01176       //                                fERROR[0]  = true;
01177       //                                fERROR[21] = true;
01178       //                                bERROR|=0x200000;
01179       //                                //cerr<<"  ERROR 21   "<<sERROR[21]<<endl;
01180       //                        }
01181       //                        headerDAV_Active = -1;
01183       checkDAVs();
01184 
01185       checkTriggerHeadersAndTrailers();
01186 
01188 
01189       if( DDU_WordsSinceLastHeader>3 && !nDMBs ){
01190         fERROR[28]=true;
01191         bERROR|=0x10000000;;
01192       }
01193 
01194       if(fDDU_Trailer){
01195         fERROR[2] = true;
01196         bERROR   |= 0x4;
01197       } // DDU Header is missing
01198       fDDU_Trailer=true;
01199       fDDU_Header=false;
01200 
01201       if( fDMB_Header || fDMB_Trailer ){
01202        // std::cout << " Ex-Err: DMB (Header, Trailer) " << std::endl;
01203         fERROR[5] = true;
01204         bERROR   |= 0x20;
01205         fCHAMB_ERR[5].insert(currentChamber);
01206         bCHAMB_ERR[currentChamber] |= 0x20;
01207         fCHAMB_ERR[0].insert(currentChamber);
01208         bCHAMB_ERR[currentChamber] |= 0x20;
01209       } // DMB Trailer is missing
01210       fDMB_Header  = false;
01211       fDMB_Trailer = false;
01212 
01213       currentChamber=-1;
01214 
01215       for(int err=0; err<nERRORS; ++err)
01216         if( fCHAMB_ERR[err].find(-1) != fCHAMB_ERR[err].end() ){
01217           fCHAMB_ERR[err].erase(-1);
01218           fCHAMB_ERR[err].insert(-2);
01219         }
01220       bCHAMB_STATUS[-2] |= bCHAMB_STATUS[-1];
01221       bCHAMB_STATUS[-1] = 0;
01222       bCHAMB_ERR[-2] |= bCHAMB_ERR[-1];
01223       bCHAMB_ERR[-1] = 0;
01224       bCHAMB_WRN[-2] |= bCHAMB_WRN[-1];
01225       bCHAMB_WRN[-1] = 0;
01226 
01227       for(int err=1; err<nERRORS; ++err)
01228         if( fCHAMB_ERR[err].find(-2) != fCHAMB_ERR[err].end() ){
01229           fCHAMB_ERR[0].insert(-2);
01230           bCHAMB_ERR[-2] |= 0x1;
01231         }
01232 
01233       dduSize[sourceID] = buf0-dduBuffers[sourceID];
01234 
01235       ++cntDDU_Trailers; // Increment DDUTrailer counter
01236 
01237       // == Combining 2 words into 24bit value
01238       DDU_WordCount = buf2[2] | ((buf2[3] & 0xFF) <<16) ;
01239 
01240       if( (DDU_WordsSinceLastHeader+4) != DDU_WordCount ){
01241         fERROR[4] = true;
01242         bERROR   |= 0x10;
01243       }
01244 
01245       if( DMB_Active!=nDMBs ){
01246         fERROR[24] = true;
01247         bERROR    |= 0x1000000;
01248       }
01249 
01250       cout<<"DDU Trailer Occurrence "<<cntDDU_Trailers<<endl;
01251       cout<<"----------------------------------------------------------"<<endl;
01252       cout<<"DDU 64-bit words = Actual - DDUcounted ="<<DDU_WordsSinceLastHeader+4<<"-"<<DDU_WordCount<<endl;
01253 
01254       // increment statistics Errors and Warnings (i=0 case is handled in DDU Header)
01255       for(int err=1; err<nERRORS; ++err){
01256         if( fERROR[err] ){
01257           fERROR[0] = true;
01258           bERROR |= 0x1;
01259           cerr<<"\nDDU Header Occurrence = "<<cntDDU_Headers;
01260           cerr<<"  ERROR "<<err<<"  " <<sERROR[err]<<endl;
01261         }
01262       }
01263       for(int wrn=1; wrn<nWARNINGS; ++wrn){
01264         if( fWARNING[wrn] ){
01265           cout<<"\nDDU Header Occurrence = "<<cntDDU_Headers;
01266           cout<<"  WARNING "<<wrn<<"  "<<sWARNING[wrn]<<endl;
01267         }
01268       }
01269 
01270       bDDU_ERR[sourceID] |= bERROR;
01271       bDDU_WRN[sourceID] |= bWARNING;
01272       sync_stats();
01273 
01274       DDU_WordsSinceLastHeader=0;
01275       DDU_WordsSinceLastTrailer=0;
01276       if (modeDDUonly) {
01277         buffer+=4;
01278         buf_1 = &(tmpbuf[0]);  // Just for safety
01279         buf0  = &(tmpbuf[4]);  // Just for safety
01280         buf1  = &(tmpbuf[8]);  // Just for safety
01281         buf2  = &(tmpbuf[12]); // Just for safety
01282         bzero(tmpbuf, sizeof(uint16_t)*16);
01283         return length-4;
01284       }
01285     }
01286 
01287     if (!modeDDUonly) {
01288       // DCC Trailer 1 && DCC Trailer 2
01289       // =VB= Added support for Sep. 2008 CMS DAQ DCC format
01290       // =VB= 04.18.09 Removed (buf2[0]&0x0003) == 0x3 check for old DCC format to satisfy older format of simulated data
01291       if( (buf1[3]&0xFF00) == 0xEF00 &&
01292           ( ((buf2[3]&0xFF00) == 0xAF00 ) 
01293           || 
01294      (( buf2[3]&0xFF00) == 0xA000 && (buf2[0]&0x0003) == 0x0) ) ){
01295         // =VB= Added check that there is no DCCHeader detected to set missing DCC Header error
01296         if(!fDCC_Header || fDCC_Trailer){
01297           fERROR[26] = true;
01298           bERROR|=0x4000000;
01299           fERROR[0] = true;
01300           bERROR|=0x1;
01301         } // DCC Header is missing
01302         fDCC_Trailer=true;
01303         fDCC_Header=false;
01304 
01305         if( fDDU_Header ){
01306           // == DDU Trailer is missing
01307           fERROR[1]=true;
01308           bERROR|=0x2;
01309           fERROR[0] = true;
01310           bERROR|=0x1;
01311         }
01312 
01313         buffer+=4;
01314         buf_1 = &(tmpbuf[0]);  // Just for safety
01315         buf0  = &(tmpbuf[4]);  // Just for safety
01316         buf1  = &(tmpbuf[8]);  // Just for safety
01317         buf2  = &(tmpbuf[12]); // Just for safety
01318         bzero(tmpbuf, sizeof(uint16_t)*16);
01319         sync_stats();
01320         return length-4;
01321       }
01322     }
01323 
01324     length-=4;
01325     buffer+=4;
01326   }
01327   //Store the tail of the buffer
01328   buf_1 = &(tmpbuf[0]);
01329   buf0  = &(tmpbuf[4]);
01330   buf1  = &(tmpbuf[8]);
01331   buf2  = &(tmpbuf[12]);
01332   memcpy((void*)tmpbuf,(void*)(buffer-16),sizeof(short)*16);
01333 
01334   if (!modeDDUonly && !fDCC_Trailer && !fDCC_Header) {
01335         fERROR[26] = true;
01336         bERROR|=0x4000000;
01337         fERROR[25] = true;
01338         bERROR|=0x2000000;
01339         fERROR[0]=true;
01340         bERROR|=0x1;
01341         sync_stats();
01342         return length;
01343         
01344   }
01345  
01346   return -2;
01347 }
01348 
01349 
01350 void CSCDCCExaminer::clear()
01351 {
01352   bzero(fERROR,   sizeof(bool)*nERRORS);
01353   bzero(fWARNING, sizeof(bool)*nWARNINGS);
01354   bzero(fSUM_ERROR,   sizeof(bool)*nERRORS);
01355   bzero(fSUM_WARNING, sizeof(bool)*nWARNINGS);
01356   bERROR = 0;
01357   bWARNING = 0;
01358   bSUM_ERROR = 0;
01359   bSUM_WARNING = 0;
01360   for(int err=0; err<nERRORS;   ++err) fCHAMB_ERR[err].clear();
01361   for(int wrn=0; wrn<nWARNINGS; ++wrn) fCHAMB_WRN[wrn].clear();
01362   bCHAMB_ERR.clear();
01363   bCHAMB_WRN.clear();
01364   bCHAMB_PAYLOAD.clear();
01365   bCHAMB_STATUS.clear();
01366   bDDU_ERR.clear();
01367   bDDU_WRN.clear();
01368   dduBuffers.clear();
01369   dduOffsets.clear();
01370   dmbBuffers.clear();
01371   dmbOffsets.clear();
01372   dduSize.clear();
01373   dmbSize.clear();
01374 }
01375 
01376 
01377 void CSCDCCExaminer::zeroCounts()
01378 {
01379   ALCT_WordsSinceLastHeader = 0;
01380   ALCT_WordsSinceLastHeaderZeroSuppressed =0;
01381   ALCT_WordCount            = 0;
01382   ALCT_WordsExpected        = 0;
01383   ALCT_ZSE                  = 0;
01384   TMB_WordsSinceLastHeader  = 0;
01385   TMB_WordCount             = 0;
01386   TMB_WordsExpected         = 0;
01387   TMB_Tbins                 = 0;
01388   CFEB_SampleWordCount      = 0;
01389   CFEB_SampleCount          = 0;
01390   CFEB_BSampleCount         = 0;
01391 }
01392 
01393 
01394 void CSCDCCExaminer::checkDAVs() 
01395 {
01396   if( DAV_ALCT ){ 
01397     fERROR[21] = true;
01398     bERROR   |= 0x200000;
01399     fCHAMB_ERR[21].insert(currentChamber);
01400     bCHAMB_ERR[currentChamber] |= 0x200000;
01401     DAV_ALCT = false;
01402   }
01403   if( DAV_TMB  ){
01404     fERROR[22] = true;
01405     bERROR   |= 0x400000;
01406     fCHAMB_ERR[22].insert(currentChamber);
01407     bCHAMB_ERR[currentChamber] |= 0x400000;
01408     DAV_TMB = false;
01409   }
01410   if( DAV_CFEB && DAV_CFEB!=-16){
01411     fERROR[23] = true;
01412     bERROR   |= 0x800000;
01413     fCHAMB_ERR[23].insert(currentChamber);
01414     bCHAMB_ERR[currentChamber] |= 0x800000;
01415     DAV_CFEB = 0;
01416   }
01417 }
01418 
01419 
01420 void CSCDCCExaminer::checkTriggerHeadersAndTrailers()
01421 {   /*
01422     std::cout << " Ex-ALCT-Word-count " << std::endl;
01423     std::cout << " ALCT Words Since Last Header: " <<  ALCT_WordsSinceLastHeader << std::endl;
01424     std::cout << " ALCT Word Count: " <<  ALCT_WordCount << std::endl;
01425     std::cout << " ALCT Words Expected: " << ALCT_WordsExpected << std::endl;
01426     */
01427   if( !fALCT_Header && ( ALCT_WordsSinceLastHeader!=ALCT_WordCount || ALCT_WordsSinceLastHeader!=ALCT_WordsExpected )
01428     && ALCT_ZSE==0 ){
01429     fERROR[9] = true;
01430     bERROR   |= 0x200;
01431     fCHAMB_ERR[9].insert(currentChamber);
01432     bCHAMB_ERR[currentChamber] |= 0x200;
01433     ALCT_WordsSinceLastHeader = 0;
01434     ALCT_WordCount            = 0;
01435     ALCT_WordsSinceLastHeader = 0;
01436     ALCT_WordsExpected        = 0;
01437   } // ALCT Word Count Error
01438 
01439 if( !fALCT_Header && (ALCT_WordsSinceLastHeader!=ALCT_WordsExpected 
01440     || ALCT_WordsSinceLastHeaderZeroSuppressed!=ALCT_WordCount) && ALCT_ZSE!=0 ){
01441     fERROR[9] = true;
01442     bERROR   |= 0x200;
01443     fCHAMB_ERR[9].insert(currentChamber);
01444     bCHAMB_ERR[currentChamber] |= 0x200;
01445     ALCT_WordsSinceLastHeaderZeroSuppressed =0;
01446     ALCT_WordsSinceLastHeader = 0;
01447     ALCT_WordCount            = 0;
01448     ALCT_WordsSinceLastHeader = 0;
01449     ALCT_WordsExpected        = 0;
01450   } // ALCT Word Count Error With zero suppression
01451 
01452   if( !fTMB_Header && ( TMB_WordsSinceLastHeader!=TMB_WordCount || TMB_WordsSinceLastHeader!=TMB_WordsExpected ) ){
01453     fERROR[14] = true;
01454     bERROR    |= 0x4000;
01455     fCHAMB_ERR[14].insert(currentChamber);
01456     bCHAMB_ERR[currentChamber] |= 0x4000;
01457     TMB_WordsSinceLastHeader = 0;
01458     TMB_WordCount            = 0;
01459     TMB_WordsSinceLastHeader = 0;
01460     TMB_WordsExpected        = 0;
01461   } // TMB Word Count Error
01462 
01463   if( (CFEB_SampleCount%8)!=0 ){
01464     fERROR[17] = true;
01465     bERROR    |= 0x20000;
01466     fCHAMB_ERR[17].insert(currentChamber);
01467     bCHAMB_ERR[currentChamber] |= 0x20000;
01468     CFEB_SampleCount = 0;
01469   } // Number of CFEB samples != 8*n
01470 
01471   if(fALCT_Header) {
01472     fERROR[7] = true;  // ALCT Trailer is missing
01473     bERROR   |= 0x80;
01474     fCHAMB_ERR[7].insert(currentChamber);
01475     bCHAMB_ERR[currentChamber] |= 0x80;
01476     ALCT_WordsSinceLastHeaderZeroSuppressed =0;
01477     ALCT_WordsSinceLastHeader = 0;
01478     ALCT_WordsExpected        = 0;
01479     fALCT_Header = 0;
01480   }
01481 
01482   if(fTMB_Header) {
01483     fERROR[12]=true;        // TMB Trailer is missing
01484     bERROR   |= 0x1000;
01485     fCHAMB_ERR[12].insert(currentChamber);
01486     bCHAMB_ERR[currentChamber] |= 0x1000;
01487     TMB_WordsSinceLastHeader = 0;
01488     TMB_WordsExpected        = 0;
01489     fTMB_Header = false;
01490   }
01491 }
01492 
01493 inline void CSCDCCExaminer::sync_stats()
01494 {
01495   for (int err=0; err<nERRORS; ++err)
01496     fSUM_ERROR[err] |= fERROR[err];
01497   for (int wrn=0; wrn<nWARNINGS; ++wrn)
01498     fSUM_WARNING[wrn] |= fWARNING[wrn];
01499   bSUM_ERROR            |= bERROR;
01500   bSUM_WARNING  |= bWARNING;
01501 }
01502 
01503 inline int CSCDCCExaminer::scanbuf(const uint16_t* &buffer, int32_t length, uint16_t sig, uint16_t mask)
01504 {
01505         for (int i=0; i<length; i++)
01506         {
01507            if ( (buffer[i]&mask) == sig) { 
01508                 return i;
01509            }
01510         }
01511         return -1;
01512 }
01513