Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-09-07 04:36:08

0001 /** \file
0002  *
0003  *  \author  M. Zanetti - INFN Padova
0004  *  \revision FRC 060906
0005  */
0006 
0007 #include <EventFilter/DTRawToDigi/plugins/DTROS25Unpacker.h>
0008 
0009 #include <DataFormats/DTDigi/interface/DTDDUWords.h>
0010 #include <DataFormats/DTDigi/interface/DTControlData.h>
0011 #include <EventFilter/DTRawToDigi/interface/DTROChainCoding.h>
0012 
0013 #include "FWCore/ServiceRegistry/interface/Service.h"
0014 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0015 
0016 #include <EventFilter/DTRawToDigi/plugins/DTTDCErrorNotifier.h>
0017 
0018 // Mapping
0019 #include <CondFormats/DTObjects/interface/DTReadOutMapping.h>
0020 
0021 #include <iostream>
0022 #include <cmath>
0023 
0024 using namespace std;
0025 using namespace edm;
0026 
0027 DTROS25Unpacker::DTROS25Unpacker(const edm::ParameterSet& ps) {
0028   localDAQ = ps.getUntrackedParameter<bool>("localDAQ", false);
0029   readingDDU = ps.getUntrackedParameter<bool>("readingDDU", true);
0030 
0031   readDDUIDfromDDU = ps.getUntrackedParameter<bool>("readDDUIDfromDDU", true);
0032   hardcodedDDUID = ps.getUntrackedParameter<int>("dduID", 770);
0033 
0034   writeSC = ps.getUntrackedParameter<bool>("writeSC", false);
0035   performDataIntegrityMonitor = ps.getUntrackedParameter<bool>("performDataIntegrityMonitor", false);
0036   debug = ps.getUntrackedParameter<bool>("debug", false);
0037 }
0038 
0039 DTROS25Unpacker::~DTROS25Unpacker() {}
0040 
0041 void DTROS25Unpacker::interpretRawData(const unsigned int* index,
0042                                        int datasize,
0043                                        int dduIDfromDDU,
0044                                        edm::ESHandle<DTReadOutMapping>& mapping,
0045                                        std::unique_ptr<DTDigiCollection>& detectorProduct,
0046                                        std::unique_ptr<DTLocalTriggerCollection>& triggerProduct,
0047                                        uint16_t rosList) {
0048   int dduID;
0049   if (readDDUIDfromDDU)
0050     dduID = dduIDfromDDU;
0051   else
0052     dduID = hardcodedDDUID;
0053 
0054   const int wordLength = 4;
0055   int numberOfWords = datasize / wordLength;
0056 
0057   int rosID = 0;
0058   DTROS25Data controlData(rosID);
0059   controlDataFromAllROS.clear();
0060 
0061   int wordCounter = 0;
0062   uint32_t word = index[swap(wordCounter)];
0063 
0064   map<uint32_t, int> hitOrder;
0065 
0066   /******************************************************
0067   / The the loop is performed with "do-while" statements
0068   / because the ORDER of the words in the event data
0069   / is assumed to be fixed. Eventual changes into the
0070   / structure should be considered as data corruption
0071   *******************************************************/
0072 
0073   // Loop on ROSs
0074   while (wordCounter < numberOfWords) {
0075     controlData.clean();
0076 
0077     rosID++;  // to be mapped;
0078 
0079     if (readingDDU) {
0080       // matching the ROS number with the enabled DDU channel
0081       if (rosID <= 12 && !((rosList & int(pow(2., (rosID - 1)))) >> (rosID - 1)))
0082         continue;
0083       if (debug)
0084         cout << "[DTROS25Unpacker]: ros list: " << rosList << " ROS ID " << rosID << endl;
0085     }
0086 
0087     // FRC prepare info for DTLocalTrigger: wheel and sector corresponding to this ROS
0088 
0089     int SCwheel = -3;
0090     int SCsector = 0;
0091     int dum1, dum2, dum3, dum4;
0092 
0093     if (writeSC && !mapping->readOutToGeometry(dduID, rosID, 1, 1, 1, SCwheel, dum1, SCsector, dum2, dum3, dum4)) {
0094       if (debug)
0095         cout << " found SCwheel: " << SCwheel << " and SCsector: " << SCsector << endl;
0096     } else {
0097       if (writeSC && debug)
0098         cout << " WARNING failed to find WHEEL and SECTOR for ROS " << rosID << " !" << endl;
0099     }
0100 
0101     // ROS Header;
0102     if (DTROSWordType(word).type() == DTROSWordType::ROSHeader) {
0103       DTROSHeaderWord rosHeaderWord(word);
0104 
0105       if (debug)
0106         cout << "[DTROS25Unpacker]: ROSHeader " << rosHeaderWord.TTCEventCounter() << endl;
0107 
0108       // container for words to be sent to DQM
0109       controlData.setROSId(rosID);
0110       controlData.addROSHeader(rosHeaderWord);
0111 
0112       // Loop on ROBs
0113       do {
0114         wordCounter++;
0115         word = index[swap(wordCounter)];
0116 
0117         // Eventual ROS Error: occurs when some errors are found in a ROB
0118         if (DTROSWordType(word).type() == DTROSWordType::ROSError) {
0119           DTROSErrorWord dtROSErrorWord(word);
0120           controlData.addROSError(dtROSErrorWord);
0121           if (debug)
0122             cout << "[DTROS25Unpacker]: ROSError, Error type " << dtROSErrorWord.errorType() << " robID "
0123                  << dtROSErrorWord.robID() << endl;
0124         }
0125 
0126         // Eventual ROS Debugging;
0127         else if (DTROSWordType(word).type() == DTROSWordType::ROSDebug) {
0128           DTROSDebugWord rosDebugWord(word);
0129           controlData.addROSDebug(rosDebugWord);
0130           if (debug)
0131             cout << "[DTROS25Unpacker]: ROSDebug, type " << rosDebugWord.debugType() << "  message "
0132                  << rosDebugWord.debugMessage() << endl;
0133         }
0134 
0135         // Check ROB header
0136         else if (DTROSWordType(word).type() == DTROSWordType::GroupHeader) {
0137           DTROBHeaderWord robHeaderWord(word);
0138           int eventID = robHeaderWord.eventID();  // from the TDCs
0139           int bunchID = robHeaderWord.bunchID();  // from the TDCs
0140           int robID = robHeaderWord.robID();      // to be mapped
0141 
0142           DTROBHeader robHeader(robID, robHeaderWord);  // IJ
0143           controlData.addROBHeader(robHeader);          // IJ
0144 
0145           if (debug)
0146             cout << "[DTROS25Unpacker] ROB: ID " << robID << " Event ID " << eventID << " BXID " << bunchID << endl;
0147 
0148           // Loop on TDCs data (headers and trailers are not there)
0149           do {
0150             wordCounter++;
0151             word = index[swap(wordCounter)];
0152 
0153             // Eventual TDC Error
0154             if (DTROSWordType(word).type() == DTROSWordType::TDCError) {
0155               DTTDCErrorWord dtTDCErrorWord(word);
0156               DTTDCError tdcError(robID, dtTDCErrorWord);
0157               controlData.addTDCError(tdcError);
0158 
0159               DTTDCErrorNotifier dtTDCError(dtTDCErrorWord);
0160               if (debug)
0161                 dtTDCError.print();
0162             }
0163 
0164             // Eventual TDC Debug
0165             else if (DTROSWordType(word).type() == DTROSWordType::TDCDebug) {
0166               if (debug)
0167                 cout << "TDC Debugging" << endl;
0168             }
0169 
0170             // The TDC information
0171             else if (DTROSWordType(word).type() == DTROSWordType::TDCMeasurement) {
0172               DTTDCMeasurementWord tdcMeasurementWord(word);
0173               DTTDCData tdcData(robID, tdcMeasurementWord);
0174               controlData.addTDCData(tdcData);
0175 
0176               int tdcID = tdcMeasurementWord.tdcID();
0177               int tdcChannel = tdcMeasurementWord.tdcChannel();
0178 
0179               if (debug)
0180                 cout << "[DTROS25Unpacker] TDC: ID " << tdcID << " Channel " << tdcChannel << " Time "
0181                      << tdcMeasurementWord.tdcTime() << endl;
0182 
0183               DTROChainCoding channelIndex(dduID, rosID, robID, tdcID, tdcChannel);
0184 
0185               hitOrder[channelIndex.getCode()]++;
0186 
0187               if (debug) {
0188                 cout << "[DTROS25Unpacker] ROAddress: DDU " << dduID << ", ROS " << rosID << ", ROB " << robID
0189                      << ", TDC " << tdcID << ", Channel " << tdcChannel << endl;
0190               }
0191 
0192               // FRC if not already done for this ROS, find wheel and sector for SC data
0193               if (writeSC && (SCsector < 1 || SCwheel < -2)) {
0194                 if (debug)
0195                   cout << " second try to find SCwheel and SCsector " << endl;
0196                 if (!mapping->readOutToGeometry(
0197                         dduID, rosID, robID, tdcID, tdcChannel, SCwheel, dum1, SCsector, dum2, dum3, dum4)) {
0198                   if (debug)
0199                     cout << " ROS " << rosID << " SC wheel " << SCwheel << " SC sector " << SCsector << endl;
0200                 } else {
0201                   if (debug)
0202                     cout << " WARNING !! ROS " << rosID << " failed again to map for SC!! " << endl;
0203                 }
0204               }
0205 
0206               // Map the RO channel to the DetId and wire
0207               DTWireId detId;
0208               // if ( ! mapping->readOutToGeometry(dduID, rosID, robID, tdcID, tdcChannel, detId)) {
0209               int wheelId, stationId, sectorId, slId, layerId, cellId;
0210               if (!mapping->readOutToGeometry(
0211                       dduID, rosID, robID, tdcID, tdcChannel, wheelId, stationId, sectorId, slId, layerId, cellId)) {
0212                 // skip the digi if the detId is invalid
0213                 if (sectorId == 0 || stationId == 0)
0214                   continue;
0215                 else
0216                   detId = DTWireId(wheelId, stationId, sectorId, slId, layerId, cellId);
0217 
0218                 if (debug)
0219                   cout << "[DTROS25Unpacker] " << detId << endl;
0220                 int wire = detId.wire();
0221 
0222                 // Produce the digi
0223                 DTDigi digi(wire, tdcMeasurementWord.tdcTime(), hitOrder[channelIndex.getCode()] - 1);
0224 
0225                 // Commit to the event
0226                 detectorProduct->insertDigi(detId.layerId(), digi);
0227               } else {
0228                 LogWarning("DTRawToDigi|DTROS25Unpacker")
0229                     << "Unable to map the RO channel: DDU " << dduID << " ROS " << rosID << " ROB " << robID << " TDC "
0230                     << tdcID << " TDC ch. " << tdcChannel;
0231                 if (debug)
0232                   cout << "[DTROS25Unpacker] ***ERROR***  Missing wire: DDU " << dduID << " ROS " << rosID << " ROB "
0233                        << robID << " TDC " << tdcID << " TDC ch. " << tdcChannel << endl;
0234               }
0235 
0236             }  // TDC information
0237 
0238           } while (DTROSWordType(word).type() != DTROSWordType::GroupTrailer &&
0239                    DTROSWordType(word).type() != DTROSWordType::ROSError);  // loop on TDC's?
0240 
0241           // Check ROB Trailer (condition already verified)
0242           if (DTROSWordType(word).type() == DTROSWordType::GroupTrailer) {
0243             DTROBTrailerWord robTrailerWord(word);
0244             controlData.addROBTrailer(robTrailerWord);
0245             if (debug)
0246               cout << "[DTROS25Unpacker]: ROBTrailer, robID  " << robTrailerWord.robID() << " eventID  "
0247                    << robTrailerWord.eventID() << " wordCount  " << robTrailerWord.wordCount() << endl;
0248           }
0249         }  // ROB header
0250 
0251         // Check the eventual Sector Collector Header
0252         else if (DTROSWordType(word).type() == DTROSWordType::SCHeader) {
0253           DTLocalTriggerHeaderWord scHeaderWord(word);
0254           if (debug)
0255             cout << "[DTROS25Unpacker]: SC header  eventID " << scHeaderWord.eventID() << endl;
0256 
0257           // RT added : first word following SCHeader is a SC private header
0258           wordCounter++;
0259           word = index[swap(wordCounter)];
0260 
0261           if (DTROSWordType(word).type() == DTROSWordType::SCData) {
0262             DTLocalTriggerSectorCollectorHeaderWord scPrivateHeaderWord(word);
0263 
0264             if (performDataIntegrityMonitor) {
0265               controlData.addSCPrivHeader(scPrivateHeaderWord);
0266             }
0267 
0268             int numofscword = scPrivateHeaderWord.NumberOf16bitWords();
0269             int leftword = numofscword;
0270 
0271             if (debug)
0272               cout << "                   SC PrivateHeader (number of words + subheader = "
0273                    << scPrivateHeaderWord.NumberOf16bitWords() << ")" << endl;
0274 
0275             // if no SC data -> no loop ;
0276             // otherwise subtract 1 word (subheader) and countdown for bx assignment
0277             if (numofscword > 0) {
0278               int bx_received = (numofscword - 1) / 2;
0279               if (debug)
0280                 cout << "                   SC number of bx read-out: " << bx_received << endl;
0281 
0282               wordCounter++;
0283               word = index[swap(wordCounter)];
0284               if (DTROSWordType(word).type() == DTROSWordType::SCData) {
0285                 //second word following SCHeader is a SC private SUB-header
0286                 leftword--;
0287 
0288                 DTLocalTriggerSectorCollectorSubHeaderWord scPrivateSubHeaderWord(word);
0289                 // read the event BX in the SC header (will be stored in SC digis)
0290                 int scEventBX = scPrivateSubHeaderWord.LocalBunchCounter();
0291                 if (debug)
0292                   cout << "                   SC trigger delay = " << scPrivateSubHeaderWord.TriggerDelay() << endl
0293                        << "                   SC bunch counter = " << scEventBX << endl;
0294 
0295                 controlData.addSCPrivSubHeader(scPrivateSubHeaderWord);
0296 
0297                 // actual loop on SC time slots
0298                 int stationGroup = 0;
0299                 do {
0300                   wordCounter++;
0301                   word = index[swap(wordCounter)];
0302                   int SCstation = 0;
0303 
0304                   if (DTROSWordType(word).type() == DTROSWordType::SCData) {
0305                     leftword--;
0306                     //RT: bx are sent from SC in reverse order starting from the one
0307                     //which stopped the spy buffer
0308                     int bx_counter = int(round((leftword + 1) / 2.));
0309 
0310                     if (debug) {
0311                       if (bx_counter < 0 || leftword < 0)
0312                         cout << "[DTROS25Unpacker]: SC data more than expected; negative bx counter reached! " << endl;
0313                     }
0314 
0315                     DTLocalTriggerDataWord scDataWord(word);
0316 
0317                     // DTSectorCollectorData scData(scDataWord, int(round(bx_counter/2.))); M.Z.
0318                     DTSectorCollectorData scData(scDataWord, bx_counter);
0319                     controlData.addSCData(scData);
0320 
0321                     if (debug) {
0322                       //cout<<"[DTROS25Unpacker]: SCData bits "<<scDataWord.SCData()<<endl;
0323                       //cout << " word in esadecimale: " << hex << word << dec << endl;
0324                       if (scDataWord.hasTrigger(0))
0325                         cout << " at BX " << bx_counter  //round(bx_counter/2.)
0326                              << " lower part has trigger! with track quality " << scDataWord.trackQuality(0) << endl;
0327                       if (scDataWord.hasTrigger(1))
0328                         cout << " at BX " << bx_counter  //round(bx_counter/2.)
0329                              << " upper part has trigger! with track quality " << scDataWord.trackQuality(1) << endl;
0330                     }
0331 
0332                     if (writeSC && SCwheel >= -2 && SCsector >= 1) {
0333                       // FRC: start constructing persistent SC objects:
0334                       // first identify the station (data come in 2 triggers per word: MB1+MB2, MB3+MB4)
0335                       if (scDataWord.hasTrigger(0) || (scDataWord.getBits(0) & 0x30)) {
0336                         if (stationGroup % 2 == 0)
0337                           SCstation = 1;
0338                         else
0339                           SCstation = 3;
0340 
0341                         // construct localtrigger for first station of this "group" ...
0342                         DTLocalTrigger localtrigger(scEventBX, bx_counter, (scDataWord.SCData()) & 0xFF);
0343                         // ... and commit it to the event
0344                         DTChamberId chamberId(SCwheel, SCstation, SCsector);
0345                         triggerProduct->insertDigi(chamberId, localtrigger);
0346                         if (debug) {
0347                           cout << "Add SC digi to the collection, for chamber: " << chamberId << endl;
0348                           localtrigger.print();
0349                         }
0350                       }
0351                       if (scDataWord.hasTrigger(1) || (scDataWord.getBits(1) & 0x30)) {
0352                         if (stationGroup % 2 == 0)
0353                           SCstation = 2;
0354                         else
0355                           SCstation = 4;
0356 
0357                         // construct localtrigger for second station of this "group" ...
0358                         DTLocalTrigger localtrigger(scEventBX, bx_counter, (scDataWord.SCData()) >> 8);
0359                         // ... and commit it to the event
0360                         DTChamberId chamberId(SCwheel, SCstation, SCsector);
0361                         triggerProduct->insertDigi(chamberId, localtrigger);
0362                         if (debug) {
0363                           cout << "Add SC digi to the collection, for chamber: " << chamberId << endl;
0364                           localtrigger.print();
0365                         }
0366                       }
0367 
0368                       stationGroup++;
0369                     }  // if writeSC
0370                   }  // if SC data
0371                 } while (DTROSWordType(word).type() != DTROSWordType::SCTrailer);
0372 
0373               }  // end SC subheader
0374             }  // end if SC send more than only its own header!
0375           }  //  end if first data following SCheader is not SCData
0376 
0377           if (DTROSWordType(word).type() == DTROSWordType::SCTrailer) {
0378             DTLocalTriggerTrailerWord scTrailerWord(word);
0379             // add infos for data integrity monitoring
0380             controlData.addSCHeader(scHeaderWord);
0381             controlData.addSCTrailer(scTrailerWord);
0382 
0383             if (debug)
0384               cout << "                   SC Trailer, # of words: " << scTrailerWord.wordCount() << endl;
0385           }
0386         }
0387 
0388       } while (DTROSWordType(word).type() != DTROSWordType::ROSTrailer);  // loop on ROBS
0389 
0390       // check ROS Trailer (condition already verified)
0391       if (DTROSWordType(word).type() == DTROSWordType::ROSTrailer) {
0392         DTROSTrailerWord rosTrailerWord(word);
0393         controlData.addROSTrailer(rosTrailerWord);
0394         if (debug)
0395           cout << "[DTROS25Unpacker]: ROSTrailer " << rosTrailerWord.EventWordCount() << endl;
0396       }
0397 
0398       // Perform dqm if requested:
0399       // DQM IS PERFORMED FOR EACH ROS SEPARATELY
0400       if (performDataIntegrityMonitor) {
0401         //  dataMonitor->processROS25(controlData, dduID, rosID);
0402         // fill the vector with ROS's control data
0403         controlDataFromAllROS.push_back(controlData);
0404       }
0405 
0406     }
0407 
0408     else if (index[swap(wordCounter)] == 0) {
0409       // in the case of odd number of words of a given ROS the header of
0410       // the next one is postponed by 4 bytes word set to 0.
0411       // rosID needs to be step back by 1 unit
0412       if (debug)
0413         cout << "[DTROS25Unpacker]: odd number of ROS words" << endl;
0414       rosID--;
0415     }  // if ROS header
0416 
0417     else {
0418       cout << "[DTROS25Unpacker]: ERROR! First word is not a ROS Header" << endl;
0419     }
0420 
0421     // (needed if there are more than 1 ROS)
0422     wordCounter++;
0423     word = index[swap(wordCounter)];
0424 
0425   }  // loop on ROS!
0426 }
0427 
0428 int DTROS25Unpacker::swap(int n) {
0429   int result = n;
0430 
0431   if (!localDAQ) {
0432     if (n % 2 == 0)
0433       result = (n + 1);
0434     if (n % 2 == 1)
0435       result = (n - 1);
0436   }
0437 
0438   return result;
0439 }