Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-05-08 23:18:48

0001 #include "EventFilter/HcalRawToDigi/interface/HcalPacker.h"
0002 #include "EventFilter/HcalRawToDigi/interface/HcalHTRData.h"
0003 #include "EventFilter/HcalRawToDigi/interface/HcalDCCHeader.h"
0004 #include "DataFormats/HcalDetId/interface/HcalGenericDetId.h"
0005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0006 #include "DataFormats/FEDRawData/interface/FEDTrailer.h"
0007 #include "FWCore/Utilities/interface/CRC16.h"
0008 
0009 HcalPacker::Collections::Collections() {
0010   hbhe = nullptr;
0011   hoCont = nullptr;
0012   hfCont = nullptr;
0013   tpCont = nullptr;
0014   zdcCont = nullptr;
0015   calibCont = nullptr;
0016 }
0017 
0018 template <class Coll, class DetIdClass>
0019 int process(const Coll* pt, const DetId& did, unsigned short* buffer, int& presamples, bool& isUS, bool& isMP) {
0020   isUS = false;
0021   isMP = false;
0022   if (pt == nullptr) {
0023     return 0;
0024   }
0025   int size = 0;
0026   typename Coll::const_iterator i = pt->find(DetIdClass(did));
0027   if (i != pt->end()) {
0028     isUS = i->zsUnsuppressed();
0029     isMP = i->zsMarkAndPass();
0030     presamples = i->presamples();
0031     size = i->size();
0032     for (int j = 0; j < size; j++) {
0033       buffer[j] = (*i)[j].raw();
0034     }
0035   }
0036   return size;
0037 }
0038 
0039 static unsigned char processTrig(const HcalTrigPrimDigiCollection* pt,
0040                                  const HcalTrigTowerDetId& tid,
0041                                  unsigned short* buffer) {
0042   if (pt == nullptr) {
0043     return 0;
0044   }
0045   int size = 0;
0046   HcalTrigPrimDigiCollection::const_iterator i = pt->find(tid);
0047   bool any_nonzero = false;
0048   if (i != pt->end()) {
0049     int presamples = i->presamples();
0050     size = i->size();
0051 
0052     for (int j = 0; j < size; j++) {
0053       buffer[j] = (*i)[j].raw();
0054       if ((buffer[j] & 0x1FF) != 0)
0055         any_nonzero = true;
0056       if (j == presamples) {
0057         buffer[j] |= 0x0200;
0058       }
0059     }
0060   }
0061   return (any_nonzero) ? (size) : (0);
0062 }
0063 
0064 int HcalPacker::findSamples(const DetId& did,
0065                             const Collections& inputs,
0066                             unsigned short* buffer,
0067                             int& presamples,
0068                             bool& isUS,
0069                             bool& isMP) const {
0070   if (!(did.det() == DetId::Hcal || (did.det() == DetId::Calo && did.subdetId() == HcalZDCDetId::SubdetectorId))) {
0071     return 0;
0072   }
0073   int size = 0;
0074   HcalGenericDetId genId(did);
0075 
0076   switch (genId.genericSubdet()) {
0077     case (HcalGenericDetId::HcalGenBarrel):
0078     case (HcalGenericDetId::HcalGenEndcap):
0079       size = process<HBHEDigiCollection, HcalDetId>(inputs.hbhe, did, buffer, presamples, isUS, isMP);
0080       break;
0081     case (HcalGenericDetId::HcalGenOuter):
0082       size = process<HODigiCollection, HcalDetId>(inputs.hoCont, did, buffer, presamples, isUS, isMP);
0083       break;
0084     case (HcalGenericDetId::HcalGenForward):
0085       size = process<HFDigiCollection, HcalDetId>(inputs.hfCont, did, buffer, presamples, isUS, isMP);
0086       break;
0087     case (HcalGenericDetId::HcalGenZDC):
0088       size = process<ZDCDigiCollection, HcalZDCDetId>(inputs.zdcCont, did, buffer, presamples, isUS, isMP);
0089       break;
0090     case (HcalGenericDetId::HcalGenCalibration):
0091       size = process<HcalCalibDigiCollection, HcalCalibDetId>(inputs.calibCont, did, buffer, presamples, isUS, isMP);
0092       break;
0093     default:
0094       size = 0;
0095   }
0096   return size;
0097 }
0098 
0099 void HcalPacker::pack(int fedid,
0100                       int dccnumber,
0101                       int nl1a,
0102                       int orbitn,
0103                       int bcn,
0104                       const Collections& inputs,
0105                       const HcalElectronicsMap& emap,
0106                       FEDRawData& output) const {
0107   std::vector<unsigned short> precdata(HcalHTRData::CHANNELS_PER_SPIGOT * HcalHTRData::MAXIMUM_SAMPLES_PER_CHANNEL);
0108   std::vector<unsigned short> trigdata(HcalHTRData::CHANNELS_PER_SPIGOT * HcalHTRData::MAXIMUM_SAMPLES_PER_CHANNEL);
0109   std::vector<unsigned char> preclen(HcalHTRData::CHANNELS_PER_SPIGOT);
0110   std::vector<unsigned char> triglen(HcalHTRData::CHANNELS_PER_SPIGOT);
0111   static const int HTRFormatVersion = 5;
0112   bool channelIsMP[HcalHTRData::CHANNELS_PER_SPIGOT];
0113 
0114   HcalHTRData spigots[15];
0115   // loop over all valid channels in the given dcc, spigot by spigot.
0116   for (int spigot = 0; spigot < 15; spigot++) {
0117     spigots[spigot].allocate(HTRFormatVersion);
0118     HcalElectronicsId exampleEId;
0119     int npresent = 0;
0120     int presamples = -1, samples = -1;
0121     bool haveUnsuppressed = false;
0122     for (int fiber = 1; fiber <= 8; fiber++) {
0123       for (int fiberchan = 0; fiberchan < 3; fiberchan++) {
0124         int linear = (fiber - 1) * 3 + fiberchan;
0125         HcalQIESample chanSample(0, 0, fiber, fiberchan, false, false);
0126         unsigned short chanid = chanSample.raw() & 0xF800;
0127         preclen[linear] = 0;
0128         channelIsMP[linear] = false;
0129 
0130         HcalElectronicsId partialEid(fiberchan, fiber, spigot, dccnumber);
0131         // does this partial id exist?
0132         HcalElectronicsId fullEid;
0133         HcalGenericDetId genId;
0134         if (!emap.lookup(partialEid, fullEid, genId)) {
0135           continue;
0136         }
0137 
0138         // next, see if there is a digi with this id
0139         unsigned short* database = &(precdata[linear * HcalHTRData::MAXIMUM_SAMPLES_PER_CHANNEL]);
0140         int mypresamples = -1;
0141         bool isUS = false, isMP = false;
0142         int mysamples = findSamples(genId, inputs, database, mypresamples, isUS, isMP);
0143         haveUnsuppressed = haveUnsuppressed || isUS;
0144         channelIsMP[linear] = isMP;
0145 
0146         if (mysamples > 0) {
0147           if (samples < 0) {
0148             samples = mysamples;
0149           } else if (samples != mysamples) {
0150             edm::LogError("HCAL") << "Mismatch of samples in a single HTR (unsupported) " << mysamples
0151                                   << " != " << samples;
0152             continue;
0153           }
0154           if (presamples < 0) {
0155             presamples = mypresamples;
0156             exampleEId = fullEid;
0157           } else if (mypresamples != presamples) {
0158             edm::LogError("HCAL") << "Mismatch of presamples in a single HTR (unsupported) " << mypresamples
0159                                   << " != " << presamples;
0160             continue;
0161           }
0162           for (int ii = 0; ii < samples; ii++) {
0163             database[ii] = (database[ii] & 0x7FF) | chanid;
0164           }
0165           preclen[linear] = (unsigned char)(samples);
0166           npresent++;
0167         }
0168       }
0169     }
0170     for (int slb = 1; slb <= 6; slb++) {
0171       for (int slbchan = 0; slbchan <= 3; slbchan++) {
0172         int linear = (slb - 1) * 4 + slbchan;
0173         HcalTriggerPrimitiveSample idCvt(0, false, slb, slbchan);
0174         unsigned short chanid = idCvt.raw() & 0xF800;
0175         triglen[linear] = 0;
0176 
0177         HcalElectronicsId partialEid(slbchan, slb, spigot, dccnumber, 0, 0, 0);
0178         // does this partial id exist?
0179         HcalElectronicsId fullEid;
0180         HcalTrigTowerDetId tid;
0181         if (!emap.lookup(partialEid, fullEid, tid)) {
0182           //      std::cout << "TPGPACK : no match for " << partialEid << std::endl;
0183           continue;
0184         }  //else std::cout << "TPGPACK : converted " << partialEid << " to " << fullEid << "/" << tid << std::endl;
0185 
0186         // finally, what about a trigger channel?
0187         if (!tid.null()) {
0188           if (presamples < 0) {
0189             exampleEId = fullEid;
0190           }
0191           unsigned short* trigbase = &(trigdata[linear * HcalHTRData::MAXIMUM_SAMPLES_PER_CHANNEL]);
0192           triglen[linear] = processTrig(inputs.tpCont, tid, trigbase);
0193           if (triglen[linear]) {
0194             npresent++;
0195           }
0196 
0197           for (unsigned char q = 0; q < triglen[linear]; q++) {
0198             trigbase[q] = (trigbase[q] & 0x7FF) | chanid;
0199           }
0200         }
0201       }
0202     }
0203     /// pack into HcalHTRData
0204     if (npresent > 0) {
0205       spigots[spigot].pack(&(preclen[0]), &(precdata[0]), &(triglen[0]), &(trigdata[0]), false);
0206       static const int pipeline = 0x22;
0207       static const int firmwareRev = 0;
0208       int submodule = exampleEId.htrTopBottom() & 0x1;
0209       submodule |= (exampleEId.htrSlot() & 0x1F) << 1;
0210       submodule |= (exampleEId.readoutVMECrateId() & 0x1f) << 6;
0211       // Samples and Presamples can't be negative, or the HeaderTrailer will
0212       // generate a large large number using them (unsigned int roll over)
0213       if (samples < 0) {
0214         samples = 0;
0215       }
0216       if (presamples < 0) {
0217         presamples = 0;
0218       }
0219       spigots[spigot].packHeaderTrailer(nl1a,
0220                                         bcn,
0221                                         submodule,
0222                                         orbitn,
0223                                         pipeline,
0224                                         samples,
0225                                         presamples,
0226                                         firmwareRev,
0227                                         1);  // need non-zero falvor
0228       if (haveUnsuppressed) {
0229         spigots[spigot].packUnsuppressed(channelIsMP);
0230       }
0231     }
0232   }
0233   // calculate the total length, and resize the FEDRawData
0234   int theSize = 0;
0235   for (int spigot = 0; spigot < 15; spigot++) {
0236     theSize += spigots[spigot].getRawLength() * sizeof(unsigned short);
0237   }
0238   theSize += sizeof(HcalDCCHeader) + 8;  // 8 for trailer
0239   theSize += (8 - (theSize % 8)) % 8;    // even number of 64-bit words.
0240   output.resize(theSize);
0241 
0242   // construct the bare DCC Header
0243   HcalDCCHeader* dcc = (HcalDCCHeader*)(output.data());
0244   dcc->clear();
0245   dcc->setHeader(fedid, bcn, nl1a, orbitn);
0246 
0247   // pack the HTR data into the FEDRawData block using HcalDCCHeader
0248   for (int spigot = 0; spigot < 15; spigot++) {
0249     if (spigots[spigot].getRawLength() > 0) {
0250       dcc->copySpigotData(spigot, spigots[spigot], true, 0);
0251     }
0252   }
0253   // trailer
0254   FEDTrailer fedTrailer(output.data() + (output.size() - 8));
0255   fedTrailer.set(
0256       output.data() + (output.size() - 8), output.size() / 8, evf::compute_crc(output.data(), output.size()), 0, 0);
0257 }