Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:10:28

0001 #include "FWCore/Framework/interface/ConsumesCollector.h"
0002 
0003 #include "FWCore/Framework/interface/one/EDProducer.h"
0004 #include "FWCore/Framework/interface/Event.h"
0005 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0006 #include "FWCore/Framework/interface/EventSetup.h"
0007 #include "FWCore/Utilities/interface/InputTag.h"
0008 
0009 #include "DataFormats/L1CSCTrackFinder/interface/L1CSCTrackCollection.h"
0010 #include "DataFormats/L1CSCTrackFinder/interface/CSCTriggerContainer.h"
0011 #include "DataFormats/L1CSCTrackFinder/interface/TrackStub.h"
0012 
0013 #include <string>
0014 
0015 class CSCTFPacker : public edm::one::EDProducer<> {
0016 private:
0017   edm::InputTag lctProducer, mbProducer, trackProducer;
0018 
0019   bool zeroSuppression;
0020   unsigned short nTBINs;
0021   unsigned short activeSectors;
0022   bool putBufferToEvent;
0023 
0024   bool swapME1strips;
0025 
0026   FILE* file;
0027 
0028   int m_minBX, m_maxBX, central_lct_bx, central_sp_bx;
0029 
0030   edm::EDGetTokenT<CSCCorrelatedLCTDigiCollection> CSCCDC_Tok;
0031   edm::EDGetTokenT<CSCTriggerContainer<csctf::TrackStub> > CSCTC_Tok;
0032   edm::EDGetTokenT<L1CSCTrackCollection> L1CSCTr_Tok;
0033 
0034 public:
0035   void produce(edm::Event& e, const edm::EventSetup& c) override;
0036 
0037   explicit CSCTFPacker(const edm::ParameterSet& conf);
0038   ~CSCTFPacker(void) override;
0039 };
0040 
0041 #include "EventFilter/CSCTFRawToDigi/src/CSCTFEvent.h"
0042 
0043 #include <strings.h>
0044 #include <cerrno>
0045 #include <iostream>
0046 #include <cstdio>
0047 
0048 #include "DataFormats/Common/interface/Handle.h"
0049 #include "FWCore/Framework/interface/ESHandle.h"
0050 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0051 #include "DataFormats/CSCDigi/interface/CSCCorrelatedLCTDigi.h"
0052 #include "DataFormats/CSCDigi/interface/CSCCorrelatedLCTDigiCollection.h"
0053 #include "DataFormats/FEDRawData/interface/FEDRawData.h"
0054 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
0055 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
0056 #include "DataFormats/MuonDetId/interface/CSCDetId.h"
0057 #include "DataFormats/FEDRawData/interface/FEDHeader.h"
0058 #include "DataFormats/FEDRawData/interface/FEDTrailer.h"
0059 #include "FWCore/Utilities/interface/CRC16.h"
0060 
0061 CSCTFPacker::CSCTFPacker(const edm::ParameterSet& conf) : edm::one::EDProducer<>() {
0062   // "Readout" configuration
0063   zeroSuppression = conf.getParameter<bool>("zeroSuppression");
0064   nTBINs = conf.getParameter<int>("nTBINs");
0065   activeSectors = conf.getParameter<int>("activeSectors");
0066 
0067   // Configuration that controls CMSSW specific stuff
0068   putBufferToEvent = conf.getParameter<bool>("putBufferToEvent");
0069   std::string outputFile = conf.getParameter<std::string>("outputFile");
0070   lctProducer = conf.getParameter<edm::InputTag>("lctProducer");
0071   mbProducer = conf.getParameter<edm::InputTag>("mbProducer");
0072   trackProducer = conf.getParameter<edm::InputTag>("trackProducer");
0073 
0074   // Swap: if(swapME1strips && me1b && !zplus) strip = 65 - strip; // 1-64 -> 64-1 :
0075   swapME1strips = conf.getParameter<bool>("swapME1strips");
0076 
0077   file = nullptr;
0078   if (outputFile.length() && (file = fopen(outputFile.c_str(), "wt")) == nullptr)
0079     throw cms::Exception("OutputFile ") << "CSCTFPacker: cannot open output file (errno=" << errno
0080                                         << "). Try outputFile=\"\"";
0081 
0082   // BX window bounds in CMSSW:
0083   m_minBX = conf.getParameter<int>("MinBX");  //3
0084   m_maxBX = conf.getParameter<int>("MaxBX");  //9
0085 
0086   // Finds central LCT BX
0087   // assumes window is odd number of bins
0088   central_lct_bx = (m_maxBX + m_minBX) / 2;
0089   // Find central SP BX
0090   // assumes window is odd number of bins
0091   central_sp_bx = int(nTBINs / 2);
0092 
0093   produces<FEDRawDataCollection>("CSCTFRawData");
0094 
0095   CSCTC_Tok =
0096       consumes<CSCTriggerContainer<csctf::TrackStub> >(edm::InputTag(mbProducer.label(), mbProducer.instance()));
0097   CSCCDC_Tok = consumes<CSCCorrelatedLCTDigiCollection>(edm::InputTag(lctProducer.label(), lctProducer.instance()));
0098   L1CSCTr_Tok = consumes<L1CSCTrackCollection>(edm::InputTag(trackProducer.label(), trackProducer.instance()));
0099 }
0100 
0101 CSCTFPacker::~CSCTFPacker(void) {
0102   if (file)
0103     fclose(file);
0104 }
0105 
0106 void CSCTFPacker::produce(edm::Event& e, const edm::EventSetup& c) {
0107   edm::Handle<CSCCorrelatedLCTDigiCollection> corrlcts;
0108   e.getByToken(CSCCDC_Tok, corrlcts);
0109 
0110   CSCSP_MEblock meDataRecord[12][7][5][9][2];  // LCT in sector X, tbin Y, station Z, csc W, and lct I
0111   bzero(&meDataRecord, sizeof(meDataRecord));
0112   CSCSPRecord meDataHeader[12][7];  // Data Block Header for sector X and tbin Y
0113   bzero(&meDataHeader, sizeof(meDataHeader));
0114 
0115   for (CSCCorrelatedLCTDigiCollection::DigiRangeIterator csc = corrlcts.product()->begin();
0116        csc != corrlcts.product()->end();
0117        csc++) {
0118     CSCCorrelatedLCTDigiCollection::Range range1 = corrlcts.product()->get((*csc).first);
0119     int lctId = 0;
0120     for (CSCCorrelatedLCTDigiCollection::const_iterator lct = range1.first; lct != range1.second; lct++, lctId++) {
0121       int station = (*csc).first.station() - 1;
0122       int cscId = (*csc).first.triggerCscId() - 1;
0123       int sector = (*csc).first.triggerSector() - 1 + ((*csc).first.endcap() == 1 ? 0 : 6);
0124       int subSector = CSCTriggerNumbering::triggerSubSectorFromLabels((*csc).first);
0125       int tbin = lct->getBX() - (central_lct_bx - central_sp_bx);  // Shift back to hardware BX window definition
0126       if (tbin > 6 || tbin < 0) {
0127         edm::LogError("CSCTFPacker|produce") << " LCT's BX=" << tbin << " is out of 0-6 window";
0128         continue;
0129       }
0130       int fpga = (subSector ? subSector - 1 : station + 1);
0131       ///std::cout<<"Front data station: "<<station<<"  sector: "<<sector<<"  subSector: "<<subSector<<"  tbin: "<<tbin<<"  cscId: "<<cscId<<"  fpga: "<<fpga<<" LCT_qual="<<lct->getQuality()<<" LCT_strip="<<lct->getStrip()<<" LCT_wire="<<lct->getKeyWG()<<std::endl;
0132 
0133       // If Det Id is within range
0134       if (sector < 0 || sector > 11 || station < 0 || station > 3 || cscId < 0 || cscId > 8 || lctId < 0 || lctId > 1) {
0135         edm::LogInfo("CSCTFPacker: CSC digi are out of range: ")
0136             << "sector=" << sector << ", station=" << station << ", cscId=" << cscId << ", lctId=" << lctId;
0137         continue;
0138       }
0139 
0140       meDataRecord[sector][tbin][fpga][cscId][lctId].clct_pattern_number = lct->getPattern();
0141       meDataRecord[sector][tbin][fpga][cscId][lctId].quality_ = lct->getQuality();
0142       meDataRecord[sector][tbin][fpga][cscId][lctId].wire_group_id = lct->getKeyWG();
0143 
0144       meDataRecord[sector][tbin][fpga][cscId][lctId].clct_pattern_id =
0145           (swapME1strips && cscId < 3 && station == 0 && (*csc).first.endcap() == 2 && lct->getStrip() < 65
0146                ? 65 - lct->getStrip()
0147                : lct->getStrip());
0148       meDataRecord[sector][tbin][fpga][cscId][lctId].csc_id = (*csc).first.triggerCscId();
0149       meDataRecord[sector][tbin][fpga][cscId][lctId].left_right = lct->getBend();
0150       meDataRecord[sector][tbin][fpga][cscId][lctId].bx0_ = 0;  //?;
0151       meDataRecord[sector][tbin][fpga][cscId][lctId].bc0_ = 0;  //?;
0152 
0153       meDataRecord[sector][tbin][fpga][cscId][lctId].me_bxn = 0;               //?
0154       meDataRecord[sector][tbin][fpga][cscId][lctId].receiver_status_er1 = 0;  // dummy
0155       meDataRecord[sector][tbin][fpga][cscId][lctId].receiver_status_dv1 = 0;  // dummy
0156       meDataRecord[sector][tbin][fpga][cscId][lctId].aligment_fifo_full = 0;   // dummy
0157 
0158       meDataRecord[sector][tbin][fpga][cscId][lctId].link_id = lct->getMPCLink();
0159       meDataRecord[sector][tbin][fpga][cscId][lctId].mpc_id = 0;               // Join with above?
0160       meDataRecord[sector][tbin][fpga][cscId][lctId].err_prop_cnt = 0;         // dummy
0161       meDataRecord[sector][tbin][fpga][cscId][lctId].receiver_status_er2 = 0;  // dummy
0162       meDataRecord[sector][tbin][fpga][cscId][lctId].receiver_status_dv2 = 0;  // dummy
0163       meDataRecord[sector][tbin][fpga][cscId][lctId].aligment_fifo_empty = 0;  // dummy
0164 
0165       if (lct->isValid()) {
0166         switch ((meDataHeader[sector][tbin].vp_bits >> (fpga * 3)) & 0x7) {
0167           case 0x0:
0168             meDataHeader[sector][tbin].vp_bits |= (0x1 << (fpga * 3));
0169             break;
0170           case 0x1:
0171             meDataHeader[sector][tbin].vp_bits |= (0x3 << (fpga * 3));
0172             break;
0173           case 0x3:
0174             meDataHeader[sector][tbin].vp_bits |= (0x7 << (fpga * 3));
0175             break;
0176           default:
0177             edm::LogInfo("CSCTFPacker: more than 3 LCTs from a single MPC in one BX!!!");
0178             continue;
0179             break;
0180         }
0181         meDataRecord[sector][tbin][fpga][cscId][lctId].valid_pattern = 1;  // for later use
0182       }
0183       meDataHeader[sector][tbin].vq_a = 0;     // no digi yet?
0184       meDataHeader[sector][tbin].vq_b = 0;     // no digi yet?
0185       meDataHeader[sector][tbin].se_bits = 0;  // dummy
0186       meDataHeader[sector][tbin].sm_bits = 0;  // dummy
0187       meDataHeader[sector][tbin].af_bits = 0;  // dummy
0188       meDataHeader[sector][tbin].bx_bits = 0;  //(lct->getBX()&??<< (fpga*3));
0189 
0190       meDataHeader[sector][tbin].spare_1 = 0;  // for later use
0191     }
0192   }
0193 
0194   CSCSP_MBblock mbDataRecord[12][2][7];  // LCT in sector X, subsector Z, tbin Y
0195   bzero(&mbDataRecord, sizeof(mbDataRecord));
0196   edm::Handle<CSCTriggerContainer<csctf::TrackStub> > barrelStubs;
0197   if (mbProducer.label() != "null") {
0198     e.getByToken(CSCTC_Tok, barrelStubs);
0199     if (barrelStubs.isValid()) {
0200       std::vector<csctf::TrackStub> stubs = barrelStubs.product()->get();
0201       for (std::vector<csctf::TrackStub>::const_iterator dt = stubs.begin(); dt != stubs.end(); dt++) {
0202         int sector = dt->sector() - 1 + (dt->endcap() == 1 ? 0 : 6);
0203         int subSector = dt->subsector() - 1;
0204         int tbin = dt->getBX() - (central_lct_bx - central_sp_bx);  // Shift back to hardware BX window definition
0205         if (tbin < 0 || tbin > 6 || sector < 0 || sector > 11 || subSector < 0 || subSector > 11) {
0206           edm::LogInfo("CSCTFPacker: CSC DT digi are out of range: ")
0207               << " sector=" << sector << "  subSector=" << subSector << "  tbin=" << tbin;
0208           continue;
0209         }
0210         mbDataRecord[sector][subSector][tbin].quality_ = dt->getQuality();
0211         mbDataRecord[sector][subSector][tbin].phi_bend_ = dt->getBend();
0212         mbDataRecord[sector][subSector][tbin].flag_ = dt->getStrip();
0213         mbDataRecord[sector][subSector][tbin].cal_ = dt->getKeyWG();
0214         mbDataRecord[sector][subSector][tbin].phi_ = dt->phiPacked();
0215         mbDataRecord[sector][subSector][tbin].bxn1_ = (dt->getBX0() >> 1) & 0x1;
0216         mbDataRecord[sector][subSector][tbin].bxn0_ = dt->getBX0() & 0x1;
0217         mbDataRecord[sector][subSector][tbin].bc0_ = dt->getPattern();
0218         mbDataRecord[sector][subSector][tbin].mb_bxn_ = dt->getCSCID();
0219         switch (subSector) {
0220           case 0:
0221             meDataHeader[sector][tbin].vq_a = 1;
0222             break;
0223           case 1:
0224             meDataHeader[sector][tbin].vq_b = 1;
0225             break;
0226           default:
0227             edm::LogInfo("CSCTFPacker: subSector=") << subSector;
0228             break;
0229         }
0230         mbDataRecord[sector][subSector][tbin].id_ = dt->getMPCLink();  // for later use
0231       }
0232     }
0233   }
0234 
0235   CSCSP_SPblock spDataRecord[12][7][3];  // Up to 3 tracks in sector X and tbin Y
0236   bzero(&spDataRecord, sizeof(spDataRecord));
0237   int nTrk[12][7];
0238   bzero(&nTrk, sizeof(nTrk));
0239 
0240   edm::Handle<L1CSCTrackCollection> tracks;
0241   if (trackProducer.label() != "null") {
0242     e.getByToken(L1CSCTr_Tok, tracks);
0243 
0244     for (L1CSCTrackCollection::const_iterator trk = tracks->begin(); trk != tracks->end(); trk++) {
0245       int sector = 6 * (trk->first.endcap() - 1) + trk->first.sector() - 1;
0246       int tbin = trk->first.BX() + central_sp_bx;  // Shift back to hardware BX window definition
0247       //std::cout<<"Track["<<nTrk[sector][tbin]<<"]  sector: "<<sector<<" tbin: "<<tbin<<std::endl;
0248       if (tbin > 6 || tbin < 0) {
0249         edm::LogError("CSCTFPacker|analyze") << " Track's BX=" << tbin << " is out of 0-6 window";
0250         continue;
0251       }
0252       if (sector < 0 || sector > 11) {
0253         edm::LogError("CSCTFPacker|analyze") << " Track's sector=" << sector << " is out of range";
0254         continue;
0255       }
0256       spDataRecord[sector][tbin][nTrk[sector][tbin]].phi_ = trk->first.localPhi();
0257       spDataRecord[sector][tbin][nTrk[sector][tbin]].sign_ = (trk->first.ptLUTAddress() >> 20) & 0x1;
0258       spDataRecord[sector][tbin][nTrk[sector][tbin]].front_rear = trk->first.front_rear();
0259       spDataRecord[sector][tbin][nTrk[sector][tbin]].charge_ = trk->first.charge_packed();  //
0260       spDataRecord[sector][tbin][nTrk[sector][tbin]].eta_ = trk->first.eta_packed();
0261 
0262       spDataRecord[sector][tbin][nTrk[sector][tbin]].halo_ = trk->first.finehalo_packed();
0263       spDataRecord[sector][tbin][nTrk[sector][tbin]].se = 0;  // dummy
0264       spDataRecord[sector][tbin][nTrk[sector][tbin]].deltaPhi12_ = trk->first.ptLUTAddress() & 0xFF;
0265       spDataRecord[sector][tbin][nTrk[sector][tbin]].deltaPhi23_ = (trk->first.ptLUTAddress() >> 8) & 0xF;
0266       spDataRecord[sector][tbin][nTrk[sector][tbin]].bxn0_ = 0;  //dummy
0267       spDataRecord[sector][tbin][nTrk[sector][tbin]].bc0_ = 0;   //dummy
0268 
0269       spDataRecord[sector][tbin][nTrk[sector][tbin]].me1_id = trk->first.me1ID();
0270       spDataRecord[sector][tbin][nTrk[sector][tbin]].me2_id = trk->first.me2ID();
0271       spDataRecord[sector][tbin][nTrk[sector][tbin]].me3_id = trk->first.me3ID();
0272       spDataRecord[sector][tbin][nTrk[sector][tbin]].me4_id = trk->first.me4ID();
0273       spDataRecord[sector][tbin][nTrk[sector][tbin]].mb_id = trk->first.mb1ID();
0274       spDataRecord[sector][tbin][nTrk[sector][tbin]].ms_id = 0;  // don't care winner()
0275 
0276       // Warning, digi copying was broken for <= CMSSW_3_8_x! The 5 lines of code below will give problems there:
0277       spDataRecord[sector][tbin][nTrk[sector][tbin]].me1_tbin = trk->first.me1Tbin();
0278       spDataRecord[sector][tbin][nTrk[sector][tbin]].me2_tbin = trk->first.me2Tbin();
0279       spDataRecord[sector][tbin][nTrk[sector][tbin]].me3_tbin = trk->first.me3Tbin();
0280       spDataRecord[sector][tbin][nTrk[sector][tbin]].me4_tbin = trk->first.me4Tbin();
0281       spDataRecord[sector][tbin][nTrk[sector][tbin]].mb_tbin = trk->first.mb1Tbin();
0282       // As the MB stubs are not saved in simulation, we want to introduce an artificial ids
0283       if (trk->first.mb1ID()) {
0284         int subSector = (trk->first.mb1ID() - 1) % 2;
0285         int MBtbin = tbin - spDataRecord[sector][tbin][nTrk[sector][tbin]].mb_tbin;
0286         if (subSector < 0 || subSector > 1 || MBtbin < 0 || MBtbin > 7 || !mbDataRecord[sector][subSector][MBtbin].id_)
0287           spDataRecord[sector][tbin][nTrk[sector][tbin]].mb_id = (subSector ? 6 : 5);
0288       }
0289       spDataRecord[sector][tbin][nTrk[sector][tbin]].id_ = nTrk[sector][tbin] + 1;  // for later use
0290 
0291       nTrk[sector][tbin]++;
0292       switch (nTrk[sector][tbin]) {
0293         case 1:
0294           meDataHeader[sector][tbin].mode1 = (trk->first.ptLUTAddress() >> 16) & 0xF;
0295           break;
0296         case 2:
0297           meDataHeader[sector][tbin].mode2 = (trk->first.ptLUTAddress() >> 16) & 0xF;
0298           break;
0299         case 3:
0300           meDataHeader[sector][tbin].mode3 = (trk->first.ptLUTAddress() >> 16) & 0xF;
0301           break;
0302         default:
0303           edm::LogInfo("More than 3 tracks from one SP in the BX");
0304           continue;
0305           break;
0306       }
0307     }
0308   }
0309 
0310   CSCSPHeader header;
0311   bzero(&header, sizeof(header));
0312 
0313   header.header_mark_1 = 0x9;
0314   header.header_mark_2 = 0x9;
0315   header.header_mark_3 = 0x9;
0316   header.header_mark_4 = 0x9;
0317 
0318   header.header_mark_5 = 0xA;
0319   header.header_mark_6 = 0xA;
0320   header.header_mark_7 = 0xA;
0321   header.header_mark_8 = 0xA;
0322 
0323   header.csr_dfc = nTBINs;
0324   header.csr_dfc |= (zeroSuppression ? 0x8 : 0x0);
0325   header.csr_dfc |= 0x7F0;  // All FPGAs are active
0326   header.skip = 0;
0327   header.sp_ersv = 2;  // Format version with block of counters
0328 
0329   CSCSPCounters counters;
0330   bzero(&counters, sizeof(counters));
0331 
0332   CSCSPTrailer trailer;
0333   bzero(&trailer, sizeof(trailer));
0334 
0335   trailer.trailer_mark_1 = 0xF;
0336   trailer.trailer_mark_2 = 0xF;
0337   trailer.trailer_mark_3 = 0x7;
0338   trailer.trailer_mark_4 = 0xF;
0339   trailer.trailer_mark_5 = 0xF;
0340   trailer.trailer_mark_6 = 0xF;
0341   trailer.trailer_mark_7 = 0xE;
0342   trailer.trailer_mark_8 = 0xE;
0343   trailer.trailer_mark_9 = 0xE;
0344   trailer.trailer_mark_10 = 0xE;
0345 
0346   unsigned short spDDUrecord[700 * 12], *pos = spDDUrecord;  // max length
0347   bzero(&spDDUrecord, sizeof(spDDUrecord));
0348   int eventNumber = e.id().event();
0349   *pos++ = 0x0000;
0350   *pos++ = 0x0000;
0351   *pos++ = 0xFFFF & eventNumber;
0352   *pos++ = 0x5000 | (eventNumber >> 16);
0353   *pos++ = 0x0000;
0354   *pos++ = 0x8000;
0355   *pos++ = 0x0001;
0356   *pos++ = 0x8000;
0357   *pos++ = 0x0000;
0358   *pos++ = 0x0000;
0359   *pos++ = 0x0000;
0360   *pos++ = 0x0000;
0361 
0362   for (int sector = 0; sector < 12; sector++) {
0363     if (!(activeSectors & (1 << sector)))
0364       continue;
0365     header.sp_trigger_sector = sector + 1;
0366     memcpy(pos, &header, 16);
0367     pos += 8;
0368     memcpy(pos, &counters, 8);
0369     pos += 4;
0370 
0371     for (int tbin = 0; tbin < nTBINs; tbin++) {
0372       memcpy(pos, &meDataHeader[sector][tbin], 16);
0373       pos += 8;
0374       for (int fpga = 0; fpga < 5; fpga++) {
0375         int nLCTs = 0;
0376         for (int link = 0; link < 3; link++) {
0377           for (int cscId = 0; cscId < 9; cscId++)
0378             for (int lctId = 0; lctId < 2; lctId++)
0379               // Only 3 LCT per BX from the same fpga are allowed (to be valid):
0380               if (meDataRecord[sector][tbin][fpga][cscId][lctId].valid_pattern &&
0381                   meDataRecord[sector][tbin][fpga][cscId][lctId].link_id == link + 1) {
0382                 memcpy(pos, &meDataRecord[sector][tbin][fpga][cscId][lctId], 8);
0383                 pos += 4;
0384                 nLCTs++;
0385               }
0386         }
0387         if (!zeroSuppression)
0388           pos += 4 * (3 - nLCTs);
0389       }
0390       for (int subSector = 0; subSector < 2; subSector++)
0391         if (!zeroSuppression || (subSector == 0 && meDataHeader[sector][tbin].vq_a) ||
0392             (subSector == 1 && meDataHeader[sector][tbin].vq_b)) {
0393           memcpy(pos, &mbDataRecord[sector][subSector][tbin], 8);
0394           pos += 4;
0395         }
0396       for (int trk = 0; trk < 3; trk++) {
0397         if (!zeroSuppression || spDataRecord[sector][tbin][trk].id_) {
0398           memcpy(pos, &spDataRecord[sector][tbin][trk], 8);
0399           pos += 4;
0400         }
0401       }
0402     }
0403     memcpy(pos, &trailer, 16);
0404     pos += 8;
0405   }
0406 
0407   *pos++ = 0x8000;
0408   *pos++ = 0x8000;
0409   *pos++ = 0xFFFF;
0410   *pos++ = 0x8000;
0411   *pos++ = 0x0000;
0412   *pos++ = 0x0000;
0413   *pos++ = 0x0000;
0414   *pos++ = 0x0000;
0415   *pos++ = 0x0000;
0416   *pos++ = 0x0000;
0417   *pos++ = 0x0000;
0418   *pos++ = 0x0000;
0419 
0420   if (putBufferToEvent) {
0421     auto data = std::make_unique<FEDRawDataCollection>();
0422     FEDRawData& fedRawData = data->FEDData((unsigned int)FEDNumbering::MINCSCTFFEDID);
0423     fedRawData.resize((pos - spDDUrecord) * sizeof(unsigned short));
0424     std::copy((unsigned char*)spDDUrecord, (unsigned char*)pos, fedRawData.data());
0425     FEDHeader csctfFEDHeader(fedRawData.data());
0426     csctfFEDHeader.set(fedRawData.data(), 0, e.id().event(), 0, FEDNumbering::MINCSCTFFEDID);
0427     FEDTrailer csctfFEDTrailer(fedRawData.data() + (fedRawData.size() - 8));
0428     csctfFEDTrailer.set(fedRawData.data() + (fedRawData.size() - 8),
0429                         fedRawData.size() / 8,
0430                         evf::compute_crc(fedRawData.data(), fedRawData.size()),
0431                         0,
0432                         0);
0433     e.put(std::move(data), "CSCTFRawData");
0434   }
0435 
0436   if (file)
0437     fwrite(spDDUrecord, 2, pos - spDDUrecord, file);
0438 }
0439 
0440 #include "FWCore/Framework/interface/MakerMacros.h"
0441 DEFINE_FWK_MODULE(CSCTFPacker);