// File: hmdcunpacker.cc // // Author (previous Co-Author) Peter Zumbruch // old Author: Walter Karig // Modified: Apr 07, 2004 by Peter Zumbruch //////////////////////////////////////////////////////////// // // HMdcUnpacker // // Unpacker for mdc data // decodes the raw list mode data and fills the HMdcRaw category // using information from the parameter containers HMdcEvReadout // and HMdcRawStruct. // For decoding the functions of HMdcDataWord are used. // Additionally the categories HMdcRawEventHeader and on purpose // the HMdcDataWord (not yet implemented) // // The constructor gives several (additional) options // when being called: // // HMdcUnpacker( subEvtId, debug, consistency ) // HMdcUnpacker( subEvtId, version, debug, consistency) // // subEvtId : subevent Id for which this // Instance is called by the Hades::eventLoop() calls to // the HldSource and derived classes // // version : decoding version for the unpacker // // version = 1, used for data since 2002-10-01 12:00:00 // includes new naming scheme for the SAMs // version = 0, used for data before 2002-10-01 12:00:00 // // if not set in the constructor or via setDecodeVersion() // the decoding is derived from the referenceRunId (if set) // or the runId // // (reference)RunId < versionSwitchId : version 0 // (reference)RunId > versionSwitchId : version 1 // // debug : additional debug features of the Unpacker for debugging // the hardware // // debug = TRUE: // // 1) Errors/Warnings are extended by // detailed informations of the dataword // (if not switched of by setQuietMode()) // 2) HMdcRawEventHeader is written out for every call // of decodeSubHeader // of the Header (not only for not zero error // words in the sub header (ROC) // 3) HMdcDataWord is written to tree (not yet implemented) // persistency changeable with setPersistencyDataWord() // // debug = FALSE: (default) // // 1) Errors/Warnings are displayed in a reduced set // (if not completely switched of by setQuietMode()) // 2) HMdcRawEventHeader is only written out for a non zero error word // in the sub header (ROC) // // consistency: enables a rough border checking on the hardware level // on the data words while decoding. // this is actually a feature of HMdcDataWord::decode() HMdcDataWord::subheader() // which is called during execute(). // // //////////////////////////////////////////////////////////// using namespace std; //#include #include #include #include #include #include "hades.h" #include "hcategory.h" #include "hdatasource.h" #include "hiterator.h" #include "hldsubevt.h" #include "hevent.h" #include "hmdcraw.h" #include "hmdcrawstruct.h" #include "hspectrometer.h" #include "hmdcdetector.h" #include "hruntimedb.h" #include "heventheader.h" #include "TROOT.h" #include "hmdcdataword.h" #include "hmdcunpacker.h" ClassImp(HMdcUnpacker) HMdcDataWord *HMdcUnpacker::dataword=0; Bool_t HMdcUnpacker::noComment=kFALSE; HMdcUnpacker::HMdcUnpacker(Int_t id , Bool_t dbg, Bool_t consisCheck) : HldUnpack() { // id = sub event id for which the unpacker is called by subEvtId = id; dataword = new HMdcDataWord(); debug=dbg; consistencyCheck=consisCheck; setDefaults(); } // ---------------------------------------------------------------------------------------------------- HMdcUnpacker::HMdcUnpacker(Int_t id, Int_t myversion, Bool_t dbg, Bool_t consisCheck) { HMdcUnpacker::HMdcUnpacker(id, dbg, consisCheck); setDecodeVersion(myversion); } // ---------------------------------------------------------------------------------------------------- HMdcUnpacker::HMdcUnpacker(const HMdcUnpacker& mdc) { subEvtId = mdc.subEvtId; dataword=mdc.dataword; } // ---------------------------------------------------------------------------------------------------- HMdcUnpacker::~HMdcUnpacker() { if(dataword) delete dataword; dataword=0; } // ---------------------------------------------------------------------------------------------------- Bool_t HMdcUnpacker::getQuietMode() { // get status of quietMode // quiet = kTRUE : messaging switch off // = kFALSE: messages are displayed return noComment; } // ---------------------------------------------------------------------------------------------------- void HMdcUnpacker::setQuietMode(Bool_t quiet) { // switch to disable all error messages and warnings from hmdcunpacker AND hmdcdataword // quiet = kTRUE : messaging switch of // = kFALSE: messages are displayed noComment = quiet; if (quiet) Warning("setQuietMode", "subEvtId %i - from now on all error and warning messages of this unpacker are skipped, be aware of the consequences", subEvtId); } // ---------------------------------------------------------------------------------------------------- void HMdcUnpacker::setContinueDecodingAfterInconsistency(Bool_t cont) { // this function is only for debugging use! // the decoding of the data words continue even if there is // unconsistency in the datawords // cont = kTRUE : continue // cont = kFALSE: skip event continueDecodingAfterInconsistency=cont; } // ---------------------------------------------------------------------------------------------------- void HMdcUnpacker::setDefaults(void) { // set the default values for all intrinsic variables // called by the constructor pReadout = NULL; standalone=kFALSE; tdcMode=0; pMdcRawEventHeaderCat=0; disableSamNrConsistencyCheck=kFALSE; mdcRawEventHeaderCatPersistency=kFALSE; mdcDataWordCatPersistency=kFALSE; fillDataWord=kFALSE; subHeaderDecodeVersion=0; maxDecodeVersion=1; setDecodeVersion(1,kFALSE); unpackerDebug=kFALSE; rocEvtHeaderSize = UNCOMPRESSED_ROC_HEADERSIZE; noComment=kFALSE; for(Int_t s=0; s<6; s++) { for(Int_t m=0; m<4; m++) { setup[s][m]=0; } } rawc=NULL; pRawCat = NULL; pMdcRawEventHeaderCat = NULL; pMdcDataWordCat = NULL; continueDecodingAfterInconsistency=kFALSE; } // ---------------------------------------------------------------------------------------------------- UInt_t HMdcUnpacker::getDecodeVersion(void) { // returns decoding version of the unpacker // // version : decoding version for the unpacker // // version = 1, used for data since 2002-10-01 12:00:00 // includes new naming scheme for the SAMs // version = 0, used for data before 2002-10-01 12:00:00 // return decodeVersion; } // ---------------------------------------------------------------------------------------------------- void HMdcUnpacker::setDecodeVersion(UInt_t version,Bool_t manual) { // set decoding version of the unpacker // // version : decoding version for the unpacker // // version = 1, used for data since 2002-10-01 12:00:00 // includes new naming scheme for the SAMs // version = 0, used for data before 2002-10-01 12:00:00 // // manual : used for internal calls if (version>maxDecodeVersion || version < 0) { Error("setDecodeVersion()", " SubEvtId %i - selected version %i out of range [0,%i] ... exiting", subEvtId, version, maxDecodeVersion); exit(EXIT_FAILURE); } else { decodeVersion=version; versionSetManual=manual; } }; // ---------------------------------------------------------------------------------------------------- void HMdcUnpacker::determineDecodeVersion(void) { // Begin_Html obsolete !!! End_Html // Begin_Html cannot be used any more since nov02, because the runId's are now End_Html // Begin_Html random numbers not containing any useful time information End_Html // Begin_Html you have to set the decode version manually with setDecodeVersion() End_Html // // method to determine from the referenceId/runId the time and so the valid version for decoding // see the discription in setDecodeVersion() // if (!versionSetManual) { determineDecodeVersionCtr++; if ( determineDecodeVersionCtr == 1) { switch(compareEventDateTimeTo(2002,10,1,12,0,0)) // 2002-10-01/12:00:00 { case 0: // "now" setDecodeVersion(1,kFALSE); break; case 1: // event before date setDecodeVersion(1,kFALSE); break; case -1: // event before date setDecodeVersion(0,kFALSE); break; default: Error("determineDecodeVersion()", " SubEvtId %i - cannot determine decode version ... exiting",subEvtId); exit(EXIT_FAILURE); break; } if (unpackerDebug) Info("determineDecodeVersion()"," SubEvtId %i - decode version: %i ",subEvtId,getDecodeVersion()); } } } // ---------------------------------------------------------------------------------------------------- TString HMdcUnpacker::myexec(char * in) { // tool to execute an arbitray unix command // the output is returned as an char pointer (maximum size 1000) Char_t textfile[1000]; FILE *pipe = gSystem->OpenPipe(in,"r"); fscanf(pipe,"%s",textfile); gSystem->ClosePipe(pipe); return TString(textfile); } // ---------------------------------------------------------------------------------------------------- Int_t HMdcUnpacker::compareEventDateTimeTo(UInt_t cyear,UInt_t cmonth, UInt_t cday,UInt_t chour,UInt_t cmin,UInt_t csec) { // function to compare were the date and time of the event is relative to the given Time and Date // returns: // // 0 : time and date are the same // 1 : time and date of event are after the given time // -1 : time and date of event are before the given time HEventHeader * header = 0; header = ((HEvent*)(gHades->getCurrentEvent()))->getHeader(); if (header != 0) { Char_t command[1000]; sprintf(command,"date --date=\"%04i-%02i-%02i %02i:%02i:%02i\" +%%s",cyear,cmonth,cday,chour,cmin,csec); Int_t ctime = atoi((myexec(command)).Data()); UInt_t date = header->getDate(); UInt_t time = header->getTime(); UInt_t year = (date & 0xFF0000) >> 16; year = (year < 94)? year + 2000 : year + 1900; UInt_t month = ((date & 0xFF00) >> 8) + 1; UInt_t day = date & 0xFF; UInt_t hour = (time & 0xFF0000) >> 16; UInt_t min = (time & 0xFF00) >> 8; UInt_t sec = (time & 0xFF); if (unpackerDebug) Info("compareEventDateTimeTo()"," SubEvtId %i - time-stamp: %04i-%02i-%02i %02i:%02i:%02i", subEvtId,year,month,day,hour,min,sec); sprintf(command,"date --date=\"%04i-%02i-%02i %02i:%02i:%02i\" +%%s",year,month,day,hour,min,sec); Int_t evttime = atoi((myexec(command)).Data()); if (evttime == ctime) return 0; if (evttime >= ctime) return 1; if (evttime <= ctime) return -1; } else { Error("compareEventDateTimeTo()", " SubEvtId %i - no data header defined in current event of gHades ... exiting" ,subEvtId); exit(EXIT_FAILURE); } return -99; } // ---------------------------------------------------------------------------------------------------- void HMdcUnpacker::print(TString parent) { // prints out the variables of the unpacker object Info(parent.Data(),"############################################################"); Info(parent.Data(),"HMdcUnpacker: ClassName %s :",this->ClassName()); Info(parent.Data(),"%s: %p ClassName %s","HMdcEvReadout",pReadout,(pReadout)?pReadout->ClassName():"---"); //!Lookup up table Info(parent.Data(),"%s: %3i ","sub event Id",subEvtId); Info(parent.Data(),"%s: %i","TdcMode",tdcMode); Info(parent.Data(),"%s: %s","debug",(debug)?"kTRUE":"kFALSE"); Info(parent.Data(),"%s: %s","consistencyCheck",(consistencyCheck)?"kTRUE":"kFALSE"); Info(parent.Data(),"%s: %s","disableSamNrConsistencyCheck",(disableSamNrConsistencyCheck)?"kTRUE":"kFALSE"); Info(parent.Data(),"%s: %s","mdcRawEventHeaderCatPersistency",(mdcRawEventHeaderCatPersistency)?"kTRUE":"kFALSE"); Info(parent.Data(),"%s: %s","mdcDataWordCatPersistency",(mdcDataWordCatPersistency)?"kTRUE":"kFALSE"); Info(parent.Data(),"%s: %s","fillDataWord",(fillDataWord)?"kTRUE":"kFALSE"); Info(parent.Data(),"%s: %s","standalone",standalone?"kTRUE":"kFALSE"); Info(parent.Data(),"%s: %3i ","decodeVersion",decodeVersion); Info(parent.Data(),"%s: %2i ","subHeaderDecodeVersion",subHeaderDecodeVersion); Info(parent.Data(),"%s: %10i ","versionSwitchId (RunId) from which on to use version 1",versionSwitchId); Info(parent.Data(),"%s: %3i ","ROC headerSize",rocEvtHeaderSize); }; // ---------------------------------------------------------------------------------------------------- Int_t HMdcUnpacker::fillMdcRawEventHeader(Int_t errorFlag, Int_t rocModule, Int_t rocNumber, Int_t rocSector, Int_t subEvtId, Int_t subEvtSize, Int_t trigType) { // function for filling the category HMdcRawEventHeader HLocation dummy; HMdcRawEventHeader *pMdcRawEventHeader= NULL; pMdcRawEventHeader = (HMdcRawEventHeader*) pMdcRawEventHeaderCat->getNewSlot(dummy); if (pMdcRawEventHeader) { pMdcRawEventHeader = new (pMdcRawEventHeader) HMdcRawEventHeader(); } else { if(!noComment) { Error("fillMdcRawEventHeader()", "SubEvtId %i - can't get slot for MdcEventHeader",subEvtId); Error("fillMdcRawEventHeader()", " ..... but continuing unpacking for the rest of this sub event!!!"); } return -2; } Int_t samNr; // samNr = sam * 2 + samPos samNr = -1; samNr = getSubEvtIdToSamNr(subEvtId); if (samNr != -1) { rocSector = pReadout->getSamNumberToSector(samNr); rocModule = pReadout->getSamNumberToModule(samNr); } else { rocSector = 0 - subEvtId; // until lookup-table sam->sector/module exists rocModule = 0 - subEvtId; // until lookup-table sam->sector/module exists } pMdcRawEventHeader->set(errorFlag, rocModule, rocNumber, rocSector, subEvtId, subEvtSize, trigType); return 0; } // ---------------------------------------------------------------------------------------------------- Int_t HMdcUnpacker::fillMdcDataWord(Int_t sector,Int_t module,Int_t mbo,Int_t tdc) { // function for filling the category HMdcDataword // Int_t entry=0; UChar_t maxentry=10; maxentry=8; HLocation dataLoc; dataLoc.set(5,0,0,0,0,0); //set location indexes dataLoc[0] = sector; dataLoc[1] = module; dataLoc[2] = mbo; dataLoc[3] = tdc; dataLoc[4] = entry; HMdcDataWord *pMdcDataWord=NULL; for (entry = 0; entry < maxentry; entry++) { pMdcDataWord = NULL; dataLoc[4] = entry; pMdcDataWord = (HMdcDataWord*) pMdcDataWordCat->getObject(dataLoc); if (!pMdcDataWord) break; // Info("HMdcUnpacker","%2i %10p ",entry,pMdcDataWord); // Info("HMdcUnpacker","s:%i m:%i mb:%2i td:%2i e:%2i ",dataLoc[0],dataLoc[1],dataLoc[2],dataLoc[3],dataLoc[4]); // dataLoc.Dump(); // pMdcDataWord->print(); } // cout << ".............................." << endl; // Info("HMdcUnpacker","%2i %10p ",entry,pMdcDataWord); // Info("HMdcUnpacker","s:%i m:%i mb:%2i td:%2i e:%2i ",dataLoc[0],dataLoc[1],dataLoc[2],dataLoc[3],dataLoc[4]); // dataLoc.Dump(); if (pMdcDataWord) { if (entry==maxentry-1) { if(!noComment) Error("fillMdcDataWord()", " SubEvtId %i - to many entries to the same location entries>%i",subEvtId,maxentry); } else { if(!noComment) { Error("fillMdcDataWord()", " SubEvtId %i - can't get empty slot for MdcDataWord",subEvtId); Error("fillMdcDataWord()", " ..... but continuing unpacking for the rest of this sub event!!!"); } } return -2; } else { pMdcDataWord = (HMdcDataWord*) pMdcDataWordCat->getSlot(dataLoc); if (pMdcDataWord) { pMdcDataWord = new (pMdcDataWord) HMdcDataWord(*dataword); pMdcDataWord->setAdress(sector,module,mbo,tdc,entry); } else { // dataLoc.Dump(); if(!noComment) { Error("fillMdcDataWord()", " SubEvtId %i - can't get slot for MdcDataWord",subEvtId); Error("fillMdcDataWord()", " ..... but continuing unpacking for the rest of this sub event!!!"); } return -2; } } return 1; } // ---------------------------------------------------------------------------------------------------- Bool_t HMdcUnpacker::testMdcSetup(Int_t s, Int_t m) { // Tests the Mdc setup if the modules are present // in the running analysis Bool_t result=kFALSE; if(setup[s][m]==0) result=kFALSE; if(setup[s][m]==1) result=kTRUE; return result; } // ---------------------------------------------------------------------------------------------------- void HMdcUnpacker::getMdcSetup() { // gets Mdc detector setup HMdcDetector* mdcDet=(HMdcDetector*)(((HSpectrometer*)(gHades->getSetup()))->getDetector("Mdc")); if (!mdcDet) { Error("getMdcSetup()"," SubEvtId %i - Mdc-Detector setup (gHades->getSetup()->getDetector(\"Mdc\")) missing.",subEvtId); } for(Int_t s=0; s<6; s++) { for(Int_t m=0; m<4; m++) { if (!mdcDet->getModule(s, m)) setup[s][m]=0; if ( mdcDet->getModule(s, m)) setup[s][m]=1; } } } // ---------------------------------------------------------------------------------------------------- Int_t HMdcUnpacker::getSubEvtIdToSamNr(Int_t subEvtId, Bool_t expectUndefined) { // determines the samNr from the subEvtId // in addition it crosschecks the samNr with the DAQ specifications // and does boundary checks by default. // You can switch it off by setDisableSamNrConsistencyCheck() Int_t samNr; // determine samNr switch(decodeVersion) { case 0: samNr = 2*(subEvtId - 201); // version before Nov02 break; case 1: samNr = subEvtId - 201; // version since Nov02 break; default: samNr = -1; } // additional checks if (disableSamNrConsistencyCheck) { if (samNr < 0) return -1; return samNr; } // additional checks by default on !! switch(decodeVersion) { case 0: if (!(200 < subEvtId && subEvtId < 300)) { if(!noComment) Error("getSubEvtIdToSamNr()"," SubEvtId %i - sub event id: %i, out of mdc range ]200,300[",subEvtId,subEvtId); return -1; } break; case 1: if (!(200 <= subEvtId && subEvtId < 300)) { if(!noComment) Error("getSubEvtIdToSamNr()"," SubEvtId %i - sub event id: %i, out of mdc range [200,300[",subEvtId,subEvtId); return -1; } break; default: samNr = -1; } Int_t rocSector = pReadout->getSamNumberToSector(samNr); if (rocSector==-1 && !expectUndefined) { if(!noComment) Error("getSubEvtIdToSamNr()", "SubEvtId %i - calculated samNr: %i is not in the lookup table (HMdcEvReadout)", subEvtId,samNr); return -1; } return samNr; } // ---------------------------------------------------------------------------------------------------- Bool_t HMdcUnpacker::checkMboRawStructBounds(Int_t sector,Int_t module, Int_t mbo, Int_t tdc , UInt_t ldataword) { // checks consistency whether ldataword is inside // the bounds of the parameter container MboRawStruct // return value // kTRUE the checks were passed // kFALSE if otherwise Int_t nMaxSec = rawc->getSize() ; if (sector >= nMaxSec || sector < 0 ) { if (!noComment) { Error("checkMboRawStructBounds", " Event: %i - SubEvtId %3i - sector %i, number out of bounds [0,%i[ for dataword 0x%x", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(),subEvtId, sector, nMaxSec, ldataword); if (unpackerDebug) dataword->dump(); } return kFALSE; } Int_t nMaxModule = (*rawc)[sector].getSize() ; if (module >= nMaxModule || module < 0 ) { if (!noComment) { Error("checkMboRawStructBounds", " Event: %i - SubEvtId %3i - module %i, number out of bounds [0,%i[ for sector: %i for dataword 0x%x ", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(),subEvtId, module, nMaxModule, sector, ldataword); if (unpackerDebug) dataword->dump(); } return kFALSE; } Int_t nMaxMbo = (*rawc)[sector][module].getSize() ; if (mbo >= nMaxMbo || mbo < 0 ) { if (!noComment) { Error("checkMboRawStructBounds", " Event: %i - SubEvtId %3i - mbo %i, number out of bounds [0,%i[ for sector: %i, module: %i for dataword 0x%x", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(),subEvtId, mbo, nMaxMbo, sector, module, ldataword); if (unpackerDebug) dataword->dump(); } return kFALSE; } Int_t nMaxTdc = (*rawc)[sector][module][mbo].getNTdcs() ; if (tdc >= nMaxTdc || tdc < 0 ) { if (!noComment) { Error("checkMboRawStructBounds", " Event: %i - SubEvtId %3i - tdc %i, number out of bounds [0,%i[ for sector: %i, module: %i, mbo: %i for dataword 0x%x", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(),subEvtId, tdc, nMaxTdc, sector, module, mbo, ldataword); if (unpackerDebug) dataword->dump(); } return kFALSE; } return kTRUE; } // ---------------------------------------------------------------------------------------------------- Bool_t HMdcUnpacker::checkMdcSetup(Int_t sector, Int_t module, UInt_t ldataword) { // checks whether module and sector are set in the MdcSetup // (dataword is only needed for debug information ) // returns kTRUE if set, kFALSE else if(!testMdcSetup(sector,module)) { if(!noComment) { Error("checkMdcSetup()"," Event: %i - SubEvtId %3i - though sector %i, module %i is excluded in the setup, this dataword: 0x%08x points to this detector.", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(), subEvtId,sector,module,ldataword); if (unpackerDebug) dataword->dump(); } return kFALSE; } return kTRUE; } // ---------------------------------------------------------------------------------------------------- void HMdcUnpacker::setTdcMode(Int_t i) { // In measurement mode the TDC accepts two hits per channel. The TDC can hereby // trigger either on on a leading and the trailing edge of a single pulse // or on two leading edges. // This influences the polarity of the hitCounter in the HMdcRaw Class: // mode 0 (default) : trigger on leading and trailing edge // (hit multiplicity nHits: +1 or +2) // mode 1 : trigger on 2 leading edges: // (hit multiplicity nHits: -1 or -2) tdcMode=(i == 0 || i == 1)? i : 0; return; } // ---------------------------------------------------------------------------------------------------- void HMdcUnpacker::setRocEvtHeaderSize(UInt_t ui) { // function to set the size in words of the ROC Header rocEvtHeaderSize=ui; } // ---------------------------------------------------------------------------------------------------- Int_t HMdcUnpacker::getTdcMode(void) { // returns mode the tdc is triggering on signals // mode 0 (default) : trigger on leading and trailing edge // mode 1 : trigger on 2 leading edges: return tdcMode; } // ---------------------------------------------------------------------------------------------------- HCategory* HMdcUnpacker::initCategory(Cat_t cat, TString catname, TString detector) { // inits the container cat // looks first whether it already exists // otherwise it is created // default for detector is "Mdc" // catname is used for Error handling HCategory * category = 0; category = (HCategory*)(((HEvent*)(gHades->getCurrentEvent()))->getCategory(cat)); if (!category) { category=(HCategory*)((HMdcDetector*)(((HSpectrometer*)(gHades->getSetup()))->getDetector(detector.Data()))->buildCategory(cat)); if (!category) { Error("initCategory()"," SubEvtId %i - can't create or get category \"%s\"",subEvtId,catname.Data()); return NULL; } if (!((HEvent*)(gHades->getCurrentEvent()))->addCategory(cat,category,detector.Data())) { Error("initCategory()"," SubEvtId %i - can't add category \"%s\" to detector \"%s\"",subEvtId,catname.Data(),detector.Data()); return NULL; } } return category; } // ---------------------------------------------------------------------------------------------------- Bool_t HMdcUnpacker::init() { // Initialisation of // - lookup table // - category for raw-level storage // - additional category if debug option // - additional Tree if debug option // - local mdc setup table for lookup getMdcSetup(); pRawCat = NULL; HRuntimeDb *rtdb = gHades->getRuntimeDb(); rawc = (HMdcRawStruct*) rtdb->getContainer("MdcRawStruct"); if (!rawc) { Error("init()"," SubEvtId %i - can't get container \"%s\" ",subEvtId,"MdcRawStruct"); return kFALSE; } if (!rawc->isStatic()) ((HParSet*)rawc)->init(); //Needs explicit initialization pReadout = (HMdcEvReadout*) rtdb->getContainer("MdcEvReadout"); if (!pReadout) { Error("init()"," SubEvtId %i - can't get MdcEvReadout", subEvtId); return kFALSE; } pRawCat = initCategory(catMdcRaw,"catMdcRaw"); if (!pRawCat) return kFALSE; pMdcRawEventHeaderCat = initCategory(catMdcRawEventHeader,"catMdcRawEventHeader"); if (!pMdcRawEventHeaderCat) return kFALSE; pMdcRawEventHeaderCat->setPersistency(mdcRawEventHeaderCatPersistency); if (debug && fillDataWord) { if (!(pMdcDataWordCat = initCategory(catMdcDataWord,"catMdcDataWord"))) return kFALSE; pMdcDataWordCat->setPersistency(mdcDataWordCatPersistency); } return kTRUE; } // ---------------------------------------------------------------------------------------------------- Bool_t HMdcUnpacker::reinit() { // reinit function // if versionSetManual not set it determines the decodeVersion via determineDecodeVersion() if (!versionSetManual) { determineDecodeVersionCtr=0; } if (unpackerDebug) print("reinit()"); return kTRUE; } // ---------------------------------------------------------------------------------------------------- Int_t HMdcUnpacker::execute() { // execute funtion of the task // calls the fill() function // before it checks whether the called subEvtId corresponds // to an active module in the mdc detector setup // checks if (!pSubEvt) return 1; if (!pReadout) { if(!noComment) { Error("execute"," Event: %i - SubEvtId %i - pointer to Lookup-Table zero", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(), subEvtId); } return 1; } Int_t samNr = getSubEvtIdToSamNr(subEvtId,kTRUE); if (samNr < 0) { if(!noComment) { Warning("execute", " Event: %i - SubEvtId %i - samNr: %i (=lookup table index+1) negative ... sub event id %i ignored", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(), subEvtId,samNr,subEvtId); } return kTRUE; } Int_t sector = pReadout->getSamNumberToSector(samNr); if (sector < 0) { if(!noComment) { if(!noComment) Warning("execute", " Event: %i - SubEvtId %i - no valid sector entry in lookuptable for virtual samNr: %i (=lookup table index+1) ... sub event id %i ignored", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(), subEvtId,samNr,subEvtId); } return kTRUE; } Int_t module = pReadout->getSamNumberToModule(samNr); if (module < 0) { if(!noComment) { if(!noComment) Warning("execute", " Event: %i - SubEvtId %i - no valid module entry in lookuptable for virtual samNr: %i (=lookup table index+1) ... sub event id %i ignored", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(), subEvtId,samNr,subEvtId); } return kTRUE; } // all checks are passed if (testMdcSetup(sector, module)) { // module in given setup ? Int_t err = fill(); // fill the data words if (err<0) { if(!noComment) { if(!noComment) Error("execute"," Event: %i - SubEvtId %i - error in unpacking", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(), subEvtId); } return kTRUE; } } return kTRUE; } // ---------------------------------------------------------------------------------------------------- Bool_t HMdcUnpacker::finalize() { // dummy finalize function // returning kTRUE; return kTRUE; } // ---------------------------------------------------------------------------------------------------- Bool_t HMdcUnpacker::decodeSubHeader(UInt_t *data, UInt_t &subEvtSize) { // decodes the sub header (ROC-Header) // and returns the size of this header // // If the errorFlag of the ROC-Header is set or // the debug flag of the unpacker is set // the header is written out to the category HMdcRawEventHeader // (set its persistency via, setPersistencyRawEventHeader()) // // If the standalone mode is chosen the trigger type (id) of the whole event // is set to the trigger type of the roc header if it is a calibration trigger // (If MDCs are not run via the common daq system, but in a standalone mode, // the event trig type is not provided in the event header (it is always 1).) Int_t errorFlag = 0; Int_t trigType = 0; Int_t rocNumber = 0; Int_t rocSector = 0; Int_t rocModule = 0; dataword->clearHeader(); if(!dataword->subHeader(data,subHeaderDecodeVersion,consistencyCheck)) { if(!noComment) Error("decodeSubHeader()","SubEvtId %i - can't decode sub header ",subEvtId); return kFALSE; } rocNumber = dataword->getRocNb(); errorFlag = dataword->getErrorFlag(); trigType = dataword->getTrigType(); subEvtSize = dataword->getSubEvtSize(); if (errorFlag!=0 || debug) { fillMdcRawEventHeader(errorFlag, rocModule, rocNumber, rocSector, subEvtId, subEvtSize, trigType); } if (standalone) { Int_t kMdc_Standalone_CalibrationEvent=9; if (trigType == kMdc_Standalone_CalibrationEvent) { ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent()))->getHeader())->setId(kMdc_Standalone_CalibrationEvent); } } return kTRUE; } // ---------------------------------------------------------------------------------------------------- Bool_t HMdcUnpacker::decodingMode(void) { // evaluates the decoding info in the sub event header // // dependent on the decoding information in the sub event header // the following modes are selected: // // the least significant byte of the decoding word determines the compression modes: // so decoding & f = // // 0 : not allowed by definition of the sub event header // // 1 : uncompressed structure // - the event contains a roc sub structure // - error bits and roc event sizes are determined from the roc headers // and filled independently to HMdcRawEventHeader // // 2 : compressed structure // - the only contains pure data words // - error informations are determined from // the second least significant byte // and assigned to all roc header synchronously // to HMdcRawEventHeader but shifted by 4 bits to the left (*16) // also the size of the complete sub event is assigned to each roc // to distinguish from the case they have a negativ sign. // // any other value: not defined Int_t rocSector = 0; Int_t rocModule = 0; UInt_t decoding = pSubEvt->getDecoding(); UInt_t compressMode = decoding & 0xf; UInt_t errorBits = decoding & 0xf0; // bits intentionally not shifted !!! switch(compressMode) { case UNCOMPRESSED: setRocEvtHeaderSize(UNCOMPRESSED_ROC_HEADERSIZE); return kTRUE; break; case COMPRESSED: setRocEvtHeaderSize(COMPRESSED_ROC_HEADERSIZE); if (errorBits!=0 || debug) { UInt_t size = pSubEvt->getSize(); UInt_t id = pSubEvt->getId() & 0x7fffffff; Int_t samNr = getSubEvtIdToSamNr(subEvtId); if (samNr != -1) { rocSector = pReadout->getSamNumberToSector(samNr); rocModule = pReadout->getSamNumberToModule(samNr); } else { rocSector = 0 - subEvtId; rocModule = 0 - subEvtId; } for (Int_t rocNumber=1; rocNumber<=5; rocNumber++) { fillMdcRawEventHeader(errorBits, rocModule, rocNumber, rocSector, subEvtId, 0-size, id); } } return kTRUE; break; case 0: if(!noComment) Error("decodingMode()"," Event: %i - SubEvtId %i - compressMode %i from decoding word 0x%x invalid ... sub event id %i ignored", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(), subEvtId,compressMode,decoding,subEvtId); return kFALSE; break; default: if(!noComment) Error("decodingMode()"," Event: %i - SubEvtId %i - compressMode %i from decoding word 0x%x invalid ... sub event id %i ignored", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(), subEvtId,compressMode,decoding,subEvtId); return kFALSE; break; } return kFALSE; } // ---------------------------------------------------------------------------------------------------- Int_t HMdcUnpacker::fill() { // fill function: // performs the loop over the subevent data // // -- if the ROC header size > 0 (change it via setRocEvtHeaderSize()) // then the roc header is decoded via decodeSubHeader() // otherwise the whole subevent is decoded as once // // -- The data loop performs the following steps // 1. call of decode for each dataword // 2. the hardware address is matched to the sector/module/mbo/tdc coordinates of HMdcRaw // via the lookup table HMdcEvReadout // 3. a new/existing slot at the corresponding address is requested // 4. the time information is filled to this slot // // -- if the debug and fillDataWord flag is set (set via setFillDataWord() and setDebug()) // the extended dataword information is written to the category HMdcDataword() // (the persistency of this container can be set via setPersistencyDataWord()) // // -- the return values of the function are: // 1 : success // -1 : Error while decoding the dataword // -1 : Error while decoding the roc header // -1 : Error while decoding the in data loop (data pointer exceeds data range) // -2 : Error while filling the to category HMdcRaw // // -- in the case that there is no entry in the lookup table // for a correctly decoded dataword there the next dataword is taken if (pSubEvt && pReadout) { if (!versionSetManual) determineDecodeVersion(); HLocation loc; loc.set(4, 0, 0, 0, 0); UInt_t* data = pSubEvt->getData(); UInt_t* end = pSubEvt->getEnd(); UInt_t subEvtSize = 0; UInt_t offset = 0; UInt_t *enddata = 0; // ---------- determine decoding mode --- affects rocEvtHeaderSize if (!decodingMode()) return -1; rocEvtHeaderSize = getRocEvtHeaderSize(); while( data < end ) { dataword->clearAll(); //decoding sub-header if (rocEvtHeaderSize > 0) { if (!decodeSubHeader(data,subEvtSize)) { if(!noComment) ErrorFillDecodeSubHeaderFailed(subEvtId); return -1; } offset = subEvtSize + rocEvtHeaderSize; enddata = data+offset; } else { enddata = end; } //decoding data word for(UInt_t* deb=data+rocEvtHeaderSize; debclear(); dataword->clearHeader(); if (deb > end) { if(!noComment) ErrorFillDataPointerExceedingRange(subEvtId,deb,end,enddata); if (continueDecodingAfterInconsistency) continue; if(!noComment) ErrorFillSkippingRestOfSubEvent(); return -1; } // >>>> here the decoding of the data word is done if(!dataword->decode(*deb, decodeVersion,consistencyCheck)) { if(!noComment && unpackerDebug) dataword->dump(); if (continueDecodingAfterInconsistency) continue; if(!noComment) ErrorFillSkippingRestOfSubEvent(); return -1; } // now the hardware address is matched to the sector/module/mbo/tdc coordinates of HMdcRaw // via the lookup table HMdcEvReadout Int_t nsam = -1; switch (decodeVersion) { case 0: nsam = dataword->getSam()*2+dataword->getSamP(); break; case 1: nsam = dataword->getVirtualSamNr(); break; } Int_t nroc = dataword->getRoc(); Int_t nrocP = dataword->getRocP(); Int_t nbus = dataword->getBus(); if (nsam <0 || nroc <0 || nrocP <0 || nbus <0) { if(!noComment) ErrorFillNoValidAddressInLookUpTable(subEvtId,*deb); if (unpackerDebug) dataword->dump(); continue; } HMdcEvReadoutBus& bus =(*pReadout)[nsam][nroc][nrocP][nbus]; Int_t sector= bus.getSec(); Int_t module= bus.getMod(); Int_t mbo = bus.getMbo(); Int_t tdc = getTdc(dataword->getTdc(),dataword->getChan()); if(!checkMdcSetup(sector,module,*deb)) continue; if(!checkMboRawStructBounds(sector,module,mbo,tdc,*deb)) continue; dataword->setAddress(sector,module,mbo,tdc,0); //set location indexes loc[0] = sector; loc[1] = module; loc[2] = mbo; loc[3] = tdc; // filling the data to the location // first get a free or existing slot HMdcRaw *pMdcRaw = NULL; pMdcRaw = (HMdcRaw*) pRawCat->getObject(loc); if (!pMdcRaw) { pMdcRaw = (HMdcRaw*) pRawCat->getSlot(loc); if (pMdcRaw) { pMdcRaw = new (pMdcRaw) HMdcRaw(); pMdcRaw->setAddress(sector,module,mbo,tdc); } else { if(!noComment) ErrorFillCannotGetSlot(subEvtId,sector,module,mbo,tdc); if (unpackerDebug) pSubEvt->dumpIt(); return -2; } } // fill the times to this slot if (!pMdcRaw->setTime(dataword->getTime(),tdcMode, noComment)) { if(!noComment) ErrorFillErrorFillingDataWord(subEvtId,*deb); if (unpackerDebug) dataword->dump(); } // fill dataWord to category HMdcDataWord if(debug && fillDataWord) fillMdcDataWord(sector,module,mbo,tdc); } data += offset; } } return 1; } // -------------------------------------------------------------------------------- void HMdcUnpacker::ErrorFillDecodeSubHeaderFailed(Int_t subEvtId) { Error("fill()"," Event: %i - SubEvtId %i - decoding of sub header (ROC) failed", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(), subEvtId); Error("fill()", " ..... skipping unpacking for the rest of this sub event!!!"); } // ------------------------------------------------------------------------------- void HMdcUnpacker::ErrorFillDataPointerExceedingRange(Int_t subEvtId,UInt_t* deb, UInt_t* end, UInt_t* enddata) { Error("fill()", " Event: %i - SubEvtId %i - data pointer %p exceeding range of sub event end %p\n with calculated end point at %p", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(), subEvtId,deb,end,enddata); } // ------------------------------------------------------------------------------- void HMdcUnpacker::ErrorFillSkippingRestOfSubEvent(void) { Error("fill()", " ..... skipping unpacking for the rest of this sub event!!!"); } // ------------------------------------------------------------------------------- void HMdcUnpacker::ErrorFillNoValidAddressInLookUpTable(Int_t subEvtId, UInt_t deb) { Error("fill()", " Event: %i - SubEvtId %3i - No valid address in lookup table [HMdcEvReadout] for this dataword: 0x%08x", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(), subEvtId, deb); } // ------------------------------------------------------------------------------- void HMdcUnpacker::ErrorFillCannotGetSlot(Int_t subEvtId, Int_t sector, Int_t module, Int_t mbo, Int_t tdc) { Error("fill()", " Event: %i - SubEvtId %i - can't get slot for s:%i m:%i mb:%i tdc:%i ...", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(), subEvtId,sector,module,mbo,tdc); Error("fill()", " ..... skipping unpacking for the rest of this sub event!!!"); } // ------------------------------------------------------------------------------- void HMdcUnpacker::ErrorFillErrorFillingDataWord(Int_t subEvtId, UInt_t deb) { Error("fill()"," Event: %i - SubEvtId %i - error filling slot for dataword 0x%08x", ((HEventHeader*)((HEvent*)(gHades->getCurrentEvent())->getHeader()))->getEventSeqNumber(), subEvtId, deb); }