//*-- AUTHORS :  Pablo Cabanelas / Hector Alvarez Pol
//*-- Created : 14/10/2005

//_HADES_CLASS_DESCRIPTION 
////////////////////////////////////////////////////////////////////////
//
//  HRpcUnpacker
//
//  This is the unpacker used to read for the first time the RPC data
//  (see RpcDataStructure in WIKI for subevent information)
//
//  This unpacker is quite robust and returns quite a lot of info for debugging
//
//  The unpacker accepts the following arguments:
//
//  HRpcUnpacker(UInt_t id, Bool_t unpaired, Int_t dbg)
//
//  where:
//
//  id                is the subEvent Id
//  unpaired=kTRUE    selects the unpaired mode of the TDCs in the TRB
//                    (the default value is unpaired=kFALSE)
//  debug             controls the debugging level and the number of messages 
//                    debug=0  only relevant errors (show-stoppers)
//                    debug=1  warning and all errors are on
//                    debug=2  additional information on read words
//                    debug=3  full decoding
//
////////////////////////////////////////////////////////////////////////

using namespace std;
#include "hrpcunpacker.h"
#include "rpcdef.h"
#include "hrpclookup.h"
#include "hrpcraw.h"
#include "hdebug.h"
#include "hades.h"
#include "hevent.h"
#include "hspectrometer.h"
#include "hdetector.h"
#include "hruntimedb.h"
#include "hcategory.h"
#include "hldsubevt.h"
#include "heventheader.h"
#include <iostream>
#include <iomanip>
#include <stdlib.h>

ClassImp(HRpcUnpacker)
  
 HRpcUnpacker::HRpcUnpacker(UInt_t id, Bool_t unpaired, Int_t dbg) {
  // constructor
  subEvtId=id;
  isUnpaired = unpaired;
  debug=dbg;
  pRawCat=NULL;
  lookup=0;
}

 Bool_t HRpcUnpacker::init(void) {
  // creates the raw category and gets the pointer to the lookup table
  pRawCat=gHades->getCurrentEvent()->getCategory(catRpcRaw);
  if (!pRawCat) {
    pRawCat=gHades->getSetup()->getDetector("Rpc")->buildCategory(catRpcRaw);
    if (!pRawCat) return kFALSE;
    gHades->getCurrentEvent()->addCategory(catRpcRaw,pRawCat,"Rpc");
  }
  loc.set(1,0);
  lookup=(HRpcLookup*)(gHades->getRuntimeDb()->getContainer("RpcLookup"));
  return kTRUE;
}

 Int_t HRpcUnpacker::execute() {
  //
  // This function fills the RPC raw data structure.
  //
  //---------------------------------------------------------------------
  /*
    The subevent Format for the RPC detector (Sep05) will look like this:
    
    # RPC Header
    
    1        size                    Length of whole subevent 
    2        0x3001                  SubEvt Decoding as 32bit Data
    3        subdetecor-ID           Non-ambiguous ID. Set to 0x221
    4        trigger tag             Trigger tag of subevent
    # subEvent
    
    5        0xbeefTTNW              Internal header, where TT is Trigger Tag and NW is the 
                   number of words of the subEvent (including header and trailer (0xdeadface)
    6        0x330d701b              first word of event 
    0x........              next word 
    0x........              next word 
    N-1      0x........             (N-5)th word of event  
    N        0xdeadface              last word 
    
    First word of the subEvent is started always as 0xbeefTTNW, and last word is 0xdeadface. 
    0xbeefTTNW is created by FPGA. 0xbeef and 0xdeadface are only markers, which is usefull 
    to checking by Etrax that data transfer is ok. FPGA is counting how many words belong to 
    each event and put this number as 0xNW. 0xTT is counter of events. Trigger tag of each 
    next event is higher by 1.
    
    daq_sniff output is something like this:
    
    size: 0x00000134  decoding: 0x00030001  id:    0x00000221  seqNr:  0x000a2e6e  
    date: 2005-09-22  time:     20:27:01    runNr: 0x42a1f5ee  expId:              
    size: 0x00000114  decoding: 0x00020001  id:    0x00000221  trigNr: 0x0000d7d7
    
    00000000:  0xbeefd741  0x230d7051  0x430058c4  0x43605589 
    00000010:  0x43805cc3  0x43f85d6b  0x430858c7  0x43605738 
    00000020:  0x43885cc4  0x43c05ec2  0x431058c6  0x43405ac5 
    00000030:  0x43905cc5  0x43c85ec2  0x432059c5  0x43485ac5 
    00000040:  0x43a05dc3  0x43d05ec2  0x432859c4  0x43505ac6 
    00000050:  0x43a85dc4  0x433059c4  0x43605bc1  0x43b05dc2 
    00000060:  0x43685bd5  0x43705bd6  0x43605db9  0x330d701b
    00000070:  0x230d7051  0x430058f0  0x43605589  0x4390552e 
    00000080:  0x43f85d6a  0x430858e6  0x436855c8  0x4380557c 
    00000090:  0x43c05ec6  0x431058f0  0x4370557e  0x4388558d 
    000000a0:  0x43c85ec7  0x432059e7  0x43405ae9  0x4390556e 
    000000b0:  0x43d05ec6  0x432859e7  0x43485ae8  0x438855eb 
    000000c0:  0x433059de  0x43505adf  0x43805cc6  0x43605bc4 
    000000d0:  0x43905cc6  0x43685bc6  0x43a05dcd  0x43705bc5 
    000000e0:  0x43a85dd0  0x43705d3b  0x43b05dcd  0x43885cc6 
    000000f0:  0x330d7021  0x240d7051  0x44f85d6e  0x340d7003 
    00000100:  0xdeadface
    
    //------------------------------------------------------------------------
    */

  HRpcRaw* pRaw=0;
  Int_t nChannel=0, nCell=-1;
  Int_t fModeFlag      =-1;    //Indicates de mode of the word (1=leading, 2=leading+width, 3=trailing)
  Int_t nId            = 0;    //trigger type
  Int_t nEvt           = 0;    //Evt Id
  Int_t nTdcEvtId      = 0;    //TdcEvt Id
  Int_t nTdc           = 0;    //Tdc Id
  Int_t nBunchId       = 0;    //Bunch Id
  UInt_t uWordCount    = 0;    //auxiliary
  UInt_t uTdcWordCount = 0;    //auxiliary
  UInt_t uBlockSize    = 0;    //Number of data words in one block
  //UInt_t *uTmp         = NULL; //auxiliary

  Char_t side='U';   
  
  //TDC Id is always 0 (known bug in TRB). We have to count TDCs 
  Int_t nCountTDCHeader = 0;
  Int_t nCountTDCTrailer = 0;
  Int_t nCountTDC = 0;
  
  nId = gHades->getCurrentEvent()->getHeader()->getId();
  
  if (nId){
    if(debug>2) Info("execute()","n\t nId: %i n",nId);  
  }
  else  
    if(debug>0)
      Warning("execute()","n t There is no Current Event !!! n\n");
  
  
  if( gHades->isCalibration()){  //FIXME
    //calibration event
    //Nothing to do for rpc detector
    // cout << "Is Calibration" << endl;
    return 1;
  }
  
  if(pSubEvt) {  
    
    UInt_t* data = pSubEvt->getData();
    UInt_t* end  = pSubEvt->getEnd();
    nEvt = gHades->getCurrentEvent()->getHeader()->getEventSeqNumber();
    
    if(debug>2) Info("execute()","n\t nEvt: %i n",nEvt);
    
    //Loop over all data in this subevt
    do {
      uWordCount++;
      
      //Scan for Internal Header: 0xbeefTTNW
      // TT = Triger Tag;  NW = Number of Words	
      if( ((*data >>16) & 0xffff)==48879 ) { 
	if(debug>1) Info("execute()","Data word: %X  (First subevent word)n",*data);
	uBlockSize = (*data) & 0x000000ff;  	
      }
      
      //Scan for TDC header
      else if ( ((*data>>28) & 0xf)==2 ){
	if(debug>1) Info("execute()","Data word: %X  (TDC header)n",*data);
	
	nTdc       = ( (*data) >> 24  ) & 0xf;    //Programmed ID of TDC
	nTdcEvtId  = ( (*data) >> 12  ) & 0xfff;  //Event ID from event counter
	nBunchId   = (*data) & 0xfff;             //Bunch ID of trigger (trigger time tag)
	
	nCountTDCHeader++; 
	
	//Scan all data words
	if(debug>2) Info("execute()"," -- TDC header 0x%08x. Tdc Id: %i. Event Id: %i. Bunch Id: %i.n",
			 *data,nTdc,nTdcEvtId,nBunchId);
	
	data++;
	uTdcWordCount=0;
 
	//after a successful TDC header, tdc info comes...
	//Only leading measurement (pairing or unpairing modes) and trailing measurement are admitted
	
	while( ( (((*data)>>28 & 0xf)==4) || (((*data)>>28 & 0xf)==5) ) && *data!=0x0 ){
	  if(debug>1) Info("execute()","Data word: %X  (TDC info)n",*data);
	  
	  //counter to set the TDC Id (BUG reading it from word)
	  if(nCountTDCHeader == (nCountTDCTrailer+1)) nCountTDC = nCountTDCHeader-1;  
	  
	  uTdcWordCount++;
	  //nChannel = (32*nTDC) + ( (*(data) >> 19 ) & 0x001f ); //nTDC IS A BUG, currently is not correct
	  nChannel = (32*nCountTDC) +  ( (*(data) >> 19 ) & 0x001f );
	  
	  if(debug>2) Info("execute()","Channel #: %i  t",nChannel);
	  
	  //Obtain the cell and side for each TDC channel from the lookup table 
	  HRpcLookupChan* dcs=lookup->getChannel(nChannel+1);
	  if (dcs){
	    dcs->getAddress(nCell,side); 
	    // FIXME: solo para el test de Nov05 "&& nCell<24)" (24 celdas)
	    if (nCell>=0) { 
	      loc[0]=nCell;   
	      pRaw=(HRpcRaw *)pRawCat->getObject(loc);
	      if(!pRaw) {                                //creating an slot for the object
		pRaw=(HRpcRaw *)pRawCat->getSlot(loc);
		if (pRaw) {
		  pRaw=new (pRaw) HRpcRaw;
		  pRaw->setCell(nCell);
		  pRaw->setChannel(nChannel);
		}
		else {
		  Error("execute()",
			"Can't get Cell or Channeln");
		  return -1;
		}
	      }
	      
	      
	      if(((*data)>>28 & 0xf)==4) { //Leading measurement
		
		if(isUnpaired) {  //if unpaired mode... leading measurement
      
                fModeFlag=1;
                pRaw->setModeFlag(fModeFlag);		

		  Float_t fVal = (*data & 0x7ffff);  //bit 0 to 18

		  if(side=='R')  {
		    if(pRaw->getRightTime()<1) pRaw->setRightTime(fVal); //Only the first leading is taken
		    pRaw->incRightNHits();
		    if(debug>2) Info("execute()","TOF: %f  TOT: %fn",pRaw->getRightTime(), 
				     pRaw->getRightTot());
		    if(pRaw->getRightNHits()>1 && debug>1) 
		      Info("execute()","nHits>1: new value %i n",pRaw->getRightNHits());
		  }
		  else  {
		    if(pRaw->getLeftTime()<1) pRaw->setLeftTime(fVal); //Only the first leading is taken
		    pRaw->incLeftNHits();
		    if(debug>2) Info("execute()","TOF: %f  TOT: %fn",pRaw->getLeftTime(), 
				     pRaw->getLeftTot());
		    if(pRaw->getLeftNHits()>1 && debug>1) 
		      Info("execute()","nHits>1: new value %i n",pRaw->getLeftNHits());
		  } 
		}
		else{                                       //if paired mode... leading time and width
  
                fModeFlag=2;
                pRaw->setModeFlag(fModeFlag);		

		  Float_t fTot = (((*data) >> 12) & 0x7f);  // Time-over-threshold
		  Float_t fVal = (*data & 0xfff);           // Leading time value
		  
		  if(side=='R')  {
		    if(pRaw->getRightTime()<1){  //Only the first leading is taken
		      pRaw->setRightTime(fVal);
		      pRaw->setRightTot(fTot);
		    }
		    pRaw->incRightNHits();
		    if(debug>2) Info("execute()","TOF: %f  TOT: %fn",pRaw->getRightTime(),
				     pRaw->getRightTot());
		    if(pRaw->getRightNHits()>1 && debug>1) 
		      Info("execute()","nHits>1: new value %i n",pRaw->getRightNHits());
		  }
		  else  {
		    if(pRaw->getLeftTime()<1){  //Only the first leading is taken
		      pRaw->setLeftTime(fVal);
		      pRaw->setLeftTot(fTot);
		    }
		    pRaw->incLeftNHits();
		    if(debug>2) Info("execute()","TOF: %f  TOT: %fn",pRaw->getLeftTime(), 
				     pRaw->getLeftTot());
		    if(pRaw->getLeftNHits()>1 && debug>1) 
		      Info("execute()","nHits>1: new value %i n",pRaw->getLeftNHits());
		  }	
		}
	      } //end of leading measurement
	      
	      
	      else if(((*data)>>28 & 0xf)==5) {  //Trailing measurement in single edge mode
                fModeFlag=3;
                pRaw->setModeFlag(fModeFlag);		
 
		if(!isUnpaired) {                     //should never be the case!
		  if(debug>0) Warning("execute()",
				      "Wrong code (5) in pairing mode n");
		  data++; 
		  continue;
		}
		
		Float_t fTrail  = (*data & 0x7ffff);     //trailing edge
		
		if(side=='R')  {
		  if(pRaw->getRightTime()==-999.){   //if there is no previous leading measurement
		    if(debug>0){
		      Warning("execute()",
			      "Evt: %i, Trailing measurement without previous leading! Skipping",nTdcEvtId);
		    }
		    data++;
		    continue;
		  }
		  Float_t preTime =  pRaw->getRightTime(); 
		  Float_t fTot = fTrail-preTime;
		  pRaw->setRightTot(fTot);
		  if(fTot>0) if(debug>2) Info("execute()","TOF: %f  TOT: %fn",
					      pRaw->getRightTime(), pRaw->getRightTot());
		  else                 //takes also negative values of fTot, and warns
		    if(debug>0)
		      Warning("execute()",
			      "Evt: %i, Trailing measurement coming before than leading measurement!",
			      nTdcEvtId); 
		}
		else  {	  
		  if(pRaw->getLeftTime()==-999.){    //if there is no previous leading measurement
		    if(debug>0){
		      Warning("execute()",
			      "Evt: %i, Trailing measurement without previous leading! Skipping",nTdcEvtId);
		    }
		    data++;
		    continue;
		  }
		  Float_t preTime =  pRaw->getLeftTime();
		  Float_t fTot = fTrail-preTime;  
		  pRaw->setLeftTot(fTot);
		  if(fTot>0) if(debug>2) Info("execute()","TOF: %f  TOT: %fn",
					      pRaw->getLeftTime(), pRaw->getLeftTot());
		  else 
		    if(debug>0)
		      Warning("execute()",
			      "Evt: %i, Trailing measurement coming before than leading measurement! Skipping",
			      nTdcEvtId);
		}
	      } //end of trailing measurement in single edge mode
	    }  // end nCells
	    else { 
	      if(debug>0){
		Warning("execute()",
			"Wrong address! Cell %in",
			nCell);
	      }
	    }
	  }//end dcs
	  else {  //if no access to the lookup table!
	    Warning("execute()",
		    "TDC channel: %i not foundn",nChannel);
	  }
	  data++;  

	}
	// End of Scan-all-data-words bucle
       	data--;
        uWordCount=uWordCount+uTdcWordCount;

      } // end of Scan-Tdc-header

      else if ( ((*data >>16) & 0xffff)==57005 ) {    //last word of the subevent
        if (uBlockSize!=uWordCount) {
                   Warning("execute()","Corrupted Block: uBlockSize=%i, uWordCount=%i n",
                                uBlockSize,uWordCount);
                   continue;
        }
	if(debug>1) Info("execute()","Data word: %X  (Last word of the subevent)n",*data);
	
      }

      else if ( ((*data >>28) & 0xf)==3 ){   // Scan for TDC Trailer
	if(debug>1) Info("execute()","Data word: %X  (TDC trailer)n",*data);
	
	nCountTDCTrailer++;
	
	UInt_t uSubBlockSize = (*data & 0xfff);
	
	if(debug>2)  Info("execute()","t uSubBlockSize =  %i n",uSubBlockSize);
	if ( uSubBlockSize != (uTdcWordCount+2) )  {
	  if(debug>0) Warning("execute()",
			      "Found %i but expecting %i words in this TDC sub-block!!!n",
			      uTdcWordCount,uSubBlockSize);
	  continue;
	}
	uTdcWordCount=0;
      }

      else if ( ((*data>>24) & 0x7)>5 && ((*data>>24) & 0x7)<14 ) {   
	// Invalid Data Word: Skipping it
	
	if(debug>0){
	  Warning("execute()",
		  "Evt: %i, Invalid TDC in Data Word! Type: %d,Skipping 0x%08x",
		  nTdcEvtId,((*data>>24) & 0x7),*data);
	  if(debug>1) pSubEvt->dumpIt();
	}	
      }

      else {           	//any other case
	if(debug>0){
	  Warning("execute()",
		  "Evt: %i, Unknow raw data word 0x%08x",
		  nTdcEvtId,*data);
	}
      } 
    } while ( ++data<end && *data!=0x0 ); //end of data
  }
  
  if(debug>1) Info("execute()","Final Generated Objects: %in",pRawCat->getEntries());
  if(debug>2) pRawCat->Dump();
  
  return 1;
}









ROOT page - Class index - Class Hierarchy - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.