Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #ifndef EventFilter_HcalRawToDigi_PackerHelp_h
0002 #define EventFilter_HcalRawToDigi_PackerHelp_h
0003 
0004 #include "DataFormats/HcalDetId/interface/HcalElectronicsId.h"
0005 #include "DataFormats/HcalDigi/interface/HcalDigiCollections.h"
0006 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
0007 #include "DataFormats/FEDRawData/interface/FEDRawData.h"
0008 #include "DataFormats/FEDRawData/interface/FEDHeader.h"
0009 #include "CondFormats/HcalObjects/interface/HcalElectronicsMap.h"
0010 #include "DataFormats/HcalDigi/interface/QIE10DataFrame.h"
0011 #include "DataFormats/HcalDigi/interface/QIE11DataFrame.h"
0012 
0013 #include <iostream>
0014 #include <cstdio>
0015 #include <vector>
0016 #include <map>
0017 #include <cmath>
0018 
0019 namespace CDFHeaderSpec {
0020   static const int OFFSET_H = 0;
0021   static const int MASK_H = 0x8;
0022   static const int OFFSET_FOV = 4;
0023   static const int MASK_FOV = 0xF;
0024   static const int OFFSET_SOURCE_ID = 8;
0025   static const int MASK_SOURCE_ID = 0xFFF;
0026   static const int OFFSET_BX_ID = 20;
0027   static const int MASK_BX_ID = 0xFFF;
0028   static const uint64_t OFFSET_LV1_ID = 32;
0029   static const int MASK_LV1_ID = 0xFFFFFF;
0030   static const int OFFSET_EVT_TY = 56;
0031   static const int MASK_EVT_TY = 0xF;
0032   static const int OFFSET_FIXED_MSB = 60;
0033   static const int MASK_FIXED_MSB = 0xF;
0034   static const uint64_t FIXED_MSB = 0x5;
0035 }  // namespace CDFHeaderSpec
0036 
0037 namespace AMC13HeaderSpec {
0038   static const int OFFSET_FIXED_LSB = 0;
0039   static const int MASK_FIXED_LSB = 0xF;
0040   static const int FIXED_LSB = 0x0;
0041   static const int OFFSET_ORN = 4;
0042   static const int MASK_ORN = 0xFFFFFFFF;
0043   static const int OFFSET_RESERVED = 36;
0044   static const int MASK_RESERVED = 0xFFFF;
0045   static const int OFFSET_NAMC = 52;
0046   static const int MASK_NAMC = 0xF;
0047   static const int OFFSET_RES = 56;
0048   static const int MASK_RES = 0xF;
0049   static const int OFFSET_UFOV = 60;
0050   static const int MASK_UFOV = 0xF;
0051 }  // namespace AMC13HeaderSpec
0052 
0053 namespace AMCHeaderSpec {
0054   static const int OFFSET_CRATE_ID = 0;
0055   static const int MASK_CRATE_ID = 0xFF;
0056   static const int OFFSET_SLOT_ID = 8;
0057   static const int MASK_SLOT_ID = 0xF;
0058   static const int OFFSET_PRESAMPLES = 12;
0059   static const int MASK_PRESAMPLES = 0xF;
0060   static const int OFFSET_AMC_NO = 16;
0061   static const int MASK_AMC_NO = 0xF;
0062   static const int OFFSET_BLK_NO = 20;
0063   static const int MASK_BLK_NO = 0xFF;
0064   static const int OFFSET_FIXED = 28;
0065   static const int MASK_FIXED = 0xF;
0066   static const int OFFSET_AMCN_SIZE = 32;
0067   static const int MASK_AMCN_SIZE = 0xFFFFFF;
0068   static const int OFFSET_C = 56;
0069   static const int MASK_C = 0x1;
0070   static const int OFFSET_V = 57;
0071   static const int MASK_V = 0x1;
0072   static const int OFFSET_P = 58;
0073   static const int MASK_P = 0x1;
0074   static const int OFFSET_E = 59;
0075   static const int MASK_E = 0x1;
0076   static const int OFFSET_S = 60;
0077   static const int MASK_S = 0x1;
0078   static const int OFFSET_M = 61;
0079   static const int MASK_M = 0x1;
0080   static const int OFFSET_L = 62;
0081   static const int MASK_L = 0x1;
0082 }  // namespace AMCHeaderSpec
0083 
0084 namespace QIE8HeaderSpec {
0085   static const int OFFSET_FIBERCHAN = 0;
0086   static const int MASK_FIBERCHAN = 0x3;
0087   static const int OFFSET_FIBER = 2;
0088   static const int MASK_FIBER = 0x1F;
0089   static const int OFFSET_CAPID = 8;
0090   static const int MASK_CAPID = 0x3;
0091   static const int OFFSET_FIBERERR = 10;
0092   static const int MASK_FIBERERR = 0x3;
0093   static const int OFFSET_FLAVOR = 12;
0094   static const int MASK_FLAVOR = 0x7;
0095   static const int OFFSET_HEADER_BIT = 15;
0096   static const int MASK_HEADER_BIT = 0x1;
0097   static const int OFFSET_TECHNICAL_DATA_TYPE = 8;
0098   static const int MASK_TECHNICAL_DATA_TYPE = 0xF;
0099 }  // namespace QIE8HeaderSpec
0100 
0101 namespace QIE10HeaderSpec {
0102   static const int OFFSET_FIBERCHAN = 0;
0103   static const int MASK_FIBERCHAN = 0x7;
0104   static const int OFFSET_FIBER = 3;
0105   static const int MASK_FIBER = 0x1F;
0106   static const int OFFSET_MP = 8;  // mark-and-pass
0107   static const int MASK_MP = 0x1;
0108   static const int OFFSET_RESERV = 9;  // reserved
0109   static const int MASK_RESERV = 0x3;
0110   static const int OFFSET_LE = 11;  // link error
0111   static const int MASK_LE = 0x1;
0112   static const int OFFSET_FLAVOR = 12;
0113   static const int MASK_FLAVOR = 0x7;
0114   static const int OFFSET_HEADER_BIT = 15;
0115   static const int MASK_HEADER_BIT = 0x1;
0116 }  // namespace QIE10HeaderSpec
0117 
0118 // QIE11 specifications for various flavors
0119 
0120 namespace QIE11HeaderSpec0 {
0121   static const int OFFSET_FIBERCHAN = 0;
0122   static const int MASK_FIBERCHAN = 0x7;
0123   static const int OFFSET_FIBER = 3;
0124   static const int MASK_FIBER = 0x1F;
0125   static const int OFFSET_CAPID = 8;
0126   static const int MASK_CAPID = 0x3;
0127   static const int OFFSET_FIBERERR = 10;
0128   static const int MASK_FIBERERR = 0x3;
0129   static const int OFFSET_FLAVOR = 12;
0130   static const int MASK_FLAVOR = 0x7;
0131   static const int OFFSET_HEADER_BIT = 15;
0132   static const int MASK_HEADER_BIT = 0x1;
0133 }  // namespace QIE11HeaderSpec0
0134 
0135 namespace QIE11HeaderSpec3 {
0136   static const int OFFSET_FIBERCHAN = 0;
0137   static const int MASK_FIBERCHAN = 0x7;
0138   static const int OFFSET_FIBER = 3;
0139   static const int MASK_FIBER = 0x1F;
0140   static const int OFFSET_MP = 8;
0141   static const int MASK_MP = 0x1;
0142   static const int OFFSET_LINKERROR = 11;
0143   static const int MASK_LINKERROR = 0x1;
0144   static const int OFFSET_FLAVOR = 12;
0145   static const int MASK_FLAVOR = 0x7;
0146   static const int OFFSET_HEADER_BIT = 15;
0147   static const int MASK_HEADER_BIT = 0x1;
0148 }  // namespace QIE11HeaderSpec3
0149 
0150 namespace TPHeaderSpec {
0151   static const int OFFSET_TOWER = 0;
0152   static const int MASK_TOWER = 0xF;
0153   static const int OFFSET_LINK = 4;
0154   static const int MASK_LINK = 0xF;
0155   static const int OFFSET_CHANID = 0;
0156   static const int MASK_CHANID = 0xFF;
0157   static const int OFFSET_RESV = 8;
0158   static const int MASK_RESV = 0x3;
0159   static const int OFFSET_TPERR = 10;
0160   static const int MASK_TPERR = 0x3;
0161   static const int OFFSET_FLAVOR = 12;
0162   static const int MASK_FLAVOR = 0x7;
0163   static const int OFFSET_HEADER_BIT = 15;
0164   static const int MASK_HEADER_BIT = 0x1;
0165   static const int OFFSET_SOI_BIT = 14;
0166   static const int MASK_SOI_BIT = 0x1;
0167 }  // namespace TPHeaderSpec
0168 
0169 namespace QIE8SampleSpec {
0170   static const int OFFSET_ADC = 0;
0171   static const int MASK_ADC = 0x7F;
0172   static const int OFFSET_CAPID = 8;
0173   static const int MASK_CAPID = 0x3;
0174   static const int OFFSET_DV = 10;
0175   static const int MASK_DV = 0x1;
0176   static const int OFFSET_ER = 11;
0177   static const int MASK_ER = 0x1;
0178 }  // namespace QIE8SampleSpec
0179 
0180 class HCalFED {
0181 public:
0182   typedef std::vector<uint16_t> uhtrData;
0183 
0184   std::vector<unsigned char> fedData;
0185   std::vector<uint64_t> AMCHeaders;
0186   std::vector<uhtrData> uhtrs;
0187   int fedId;
0188   uint64_t AMC13Header, cdfHeader;
0189   uint64_t OrbitNum;
0190   uint64_t EventNum;
0191   uint64_t BxNum;
0192   uint64_t Crate;
0193 
0194   unsigned char cdfh[8];
0195   FEDHeader* rawFEDHeader;
0196 
0197   HCalFED(int fedId_, uint64_t EventNum_ = 9999, uint64_t OrbitNum_ = 999, uint64_t BxNum_ = 99) {
0198     fedId = fedId_;
0199     OrbitNum = OrbitNum_;
0200     EventNum = EventNum_;
0201     BxNum = BxNum_;
0202     Crate = fedId - FEDNumbering::MINHCALuTCAFEDID;
0203 
0204     setCDFHeader();
0205     setAMC13Header();
0206   };
0207 
0208   inline void split64bitTo8bit(std::vector<unsigned char>& outVec, const uint64_t& var64bit) {
0209     for (int is = 0; is < 8; is++) {  // 64/8 = 8
0210       outVec.push_back((var64bit >> (is * 8)) & 0xFF);
0211     }
0212   }
0213 
0214   void setCDFHeader() {
0215     cdfHeader = 0;
0216     cdfHeader |= (0x1 & CDFHeaderSpec::MASK_H) << CDFHeaderSpec::OFFSET_H;
0217     cdfHeader |= (0x0 & CDFHeaderSpec::MASK_FOV) << CDFHeaderSpec::OFFSET_FOV;
0218     cdfHeader |= ((fedId)&CDFHeaderSpec::MASK_SOURCE_ID)
0219                  << CDFHeaderSpec::OFFSET_SOURCE_ID;                                  // needs to be configurable
0220     cdfHeader |= (BxNum & CDFHeaderSpec::MASK_BX_ID) << CDFHeaderSpec::OFFSET_BX_ID;  // needs to be configurable
0221     cdfHeader |= (uint64_t(0x1) & CDFHeaderSpec::MASK_LV1_ID) << CDFHeaderSpec::OFFSET_LV1_ID;
0222     cdfHeader |= (uint64_t(0x1) & CDFHeaderSpec::MASK_EVT_TY) << CDFHeaderSpec::OFFSET_EVT_TY;
0223     cdfHeader |= (CDFHeaderSpec::FIXED_MSB & CDFHeaderSpec::MASK_FIXED_MSB) << CDFHeaderSpec::OFFSET_FIXED_MSB;
0224   }
0225 
0226   void setAMC13Header() {
0227     AMC13Header = 0;
0228     AMC13Header |= (AMC13HeaderSpec::FIXED_LSB & AMC13HeaderSpec::MASK_FIXED_LSB) << AMC13HeaderSpec::OFFSET_FIXED_LSB;
0229     AMC13Header |= ((OrbitNum + 1) & AMC13HeaderSpec::MASK_ORN) << AMC13HeaderSpec::OFFSET_ORN;
0230     AMC13Header |= (uint64_t(0x0) & AMC13HeaderSpec::MASK_RESERVED) << AMC13HeaderSpec::OFFSET_RESERVED;
0231     AMC13Header |= (uint64_t(0x0) & AMC13HeaderSpec::MASK_NAMC) << AMC13HeaderSpec::OFFSET_NAMC;
0232     AMC13Header |= (uint64_t(0x0) & AMC13HeaderSpec::MASK_RES) << AMC13HeaderSpec::OFFSET_RES;
0233     AMC13Header |= (uint64_t(0x1) & AMC13HeaderSpec::MASK_UFOV) << AMC13HeaderSpec::OFFSET_UFOV;
0234   }
0235 
0236   void setNAMC(uint64_t NAMC) { AMC13Header |= (NAMC & AMC13HeaderSpec::MASK_NAMC) << AMC13HeaderSpec::OFFSET_NAMC; }
0237 
0238   void addAMCHeader(uint64_t crate, uint64_t slot, uint64_t AMCsize, uint64_t presamples = 10, uint64_t blockNum = 0) {
0239     uint64_t header = 0;
0240     header |= (crate & AMCHeaderSpec::MASK_CRATE_ID) << AMCHeaderSpec::OFFSET_CRATE_ID;
0241     header |= (slot & AMCHeaderSpec::MASK_SLOT_ID) << AMCHeaderSpec::OFFSET_SLOT_ID;
0242     header |= (presamples & AMCHeaderSpec::MASK_PRESAMPLES) << AMCHeaderSpec::OFFSET_PRESAMPLES;  // boardId
0243     header |= (slot & AMCHeaderSpec::MASK_AMC_NO) << AMCHeaderSpec::OFFSET_AMC_NO;                // AMC no.
0244     header |= (blockNum & AMCHeaderSpec::MASK_BLK_NO) << AMCHeaderSpec::OFFSET_BLK_NO;            // Block No.
0245     header |= (AMCsize & AMCHeaderSpec::MASK_AMCN_SIZE) << AMCHeaderSpec::OFFSET_AMCN_SIZE;       // size
0246     header |= uint64_t(0x1) << AMCHeaderSpec::OFFSET_C;                                           // CRC is valid
0247     header |= uint64_t(0x1) << AMCHeaderSpec::OFFSET_V;                                           // EvN, BcN match
0248     header |= uint64_t(0x1) << AMCHeaderSpec::OFFSET_P;  // Present, header is only made if data is present
0249     header |= uint64_t(0x1) << AMCHeaderSpec::OFFSET_E;  // Enabled, header is only made if AMC is enabled
0250     header |= uint64_t(0x0) << AMCHeaderSpec::OFFSET_S;  // Segmented, always zero for unsegmented data
0251     header |= uint64_t(0x0) << AMCHeaderSpec::OFFSET_M;  // More data
0252     header |= uint64_t(0x0) << AMCHeaderSpec::OFFSET_L;  // Indicates length error
0253 
0254     AMCHeaders.push_back(header);
0255   }
0256 
0257   void addUHTR(uhtrData uhtr, uint64_t crate, uint64_t slot) {
0258     // push uhtr data into FED container
0259     uhtrs.push_back(uhtr);
0260     // create the corresponding AMC header
0261     addAMCHeader(crate, slot, uhtr.size() / 4);
0262   };
0263 
0264   // does not include HEADER and TRAILER
0265   void formatFEDdata(FEDRawData& rawData) {
0266     //std::vector<unsigned char> output;
0267     if (uhtrs.size() != AMCHeaders.size()) {
0268       return;
0269     }
0270 
0271     // put common data format header in fed container
0272     split64bitTo8bit(fedData, cdfHeader);
0273 
0274     // set the number of AMCs in the AMC13 header
0275     setNAMC(uhtrs.size());
0276     // put the AMC13 header into the fed container
0277     split64bitTo8bit(fedData, AMC13Header);
0278 
0279     // fill fedData with AMC headers
0280     for (unsigned int iAMC = 0; iAMC < AMCHeaders.size(); ++iAMC) {
0281       // adjust the AMCsize bits to match uhtr header
0282       //AMCHeaders[iAMC] |= uint64_t(uhtrs[iAMC][1]&0xF)<<51 ;
0283       //AMCHeaders[iAMC] |= uint64_t(uhtrs[iAMC][0]&0xFFFF)<<47 ;
0284       split64bitTo8bit(fedData, AMCHeaders[iAMC]);
0285     }
0286 
0287     // fill fedData with AMC data
0288     for (unsigned int iAMC = 0; iAMC < uhtrs.size(); ++iAMC) {
0289       unsigned int nWords16 = uhtrs[iAMC].size();
0290       for (unsigned int amcWord = 0; amcWord < nWords16; ++amcWord) {
0291         fedData.push_back((uhtrs[iAMC][amcWord] >> 0) & 0xFF);  // split 16-bit words into 8-bit
0292         fedData.push_back((uhtrs[iAMC][amcWord] >> 8) & 0xFF);
0293       }  // end loop over uhtr words
0294     }  // end loop over uhtrs
0295 
0296     // fedData should be a integer number of 64 bit words
0297     while (fedData.size() % 8 != 0)
0298       fedData.push_back(0);
0299 
0300     // convert to the correct format
0301     rawData.resize(fedData.size());
0302     unsigned char* words = reinterpret_cast<unsigned char*>(rawData.data());
0303 
0304     for (unsigned int i = 0; i < fedData.size(); ++i) {
0305       *words = fedData[i];
0306       words++;
0307     }
0308   };
0309 };
0310 
0311 class UHTRpacker {
0312 public:
0313   typedef std::vector<uint16_t> uhtrData;
0314   typedef std::map<int, uhtrData> UHTRMap;  // the int here is intended to be the raw electronics ID
0315 
0316   UHTRMap uhtrs;
0317 
0318   // FIRST WORD
0319   static const int OFFSET_DATA_LENGTH = 0;
0320   static const int MASK_DATA_LENGTH = 0xFFFFF;
0321   static const int OFFSET_BCN = 20;
0322   static const int MASK_BCN = 0xFFF;
0323   static const int OFFSET_EVN = 32;
0324   static const int MASK_EVN = 0xFFFFFF;
0325   static const int OFFSET_FILED_BY_AMC13 = 56;
0326   static const int MASK_FILED_BY_AMC13 = 0xFF;
0327   // SECOND WORD
0328   static const int OFFSET_CRATE_ID = 0;
0329   static const int MASK_CRATE_ID = 0xFFFFFF;
0330   static const int OFFSET_SLOT_ID = 8;
0331   static const int MASK_SLOT_ID = 0xF;
0332   static const int OFFSET_PRESAMPLES = 12;
0333   static const int MASK_PRESAMPLES = 0xF;
0334   static const int OFFSET_ORN = 16;
0335   static const int MASK_ORN = 0xFFFF;
0336   static const int OFFSET_FW_FLAVOR = 32;
0337   static const int MASK_FW_FLAVOR = 0xFF;
0338   static const int OFFSET_EVENT_TYPE = 40;
0339   static const int MASK_EVENT_TYPE = 0xF;
0340   static const int OFFSET_PAYLOAD_FORMAT = 44;
0341   static const int MASK_PAYLOAD_FORMAT = 0xF;
0342   static const int OFFSET_FW_VERSION = 48;
0343   static const int MASK_FW_VERSION = 0xFFFF;
0344 
0345   UHTRpacker() {}
0346 
0347   bool exist(int uhtrIndex) { return uhtrs.count(uhtrIndex) != 0; };
0348 
0349   // flavor should be 5, or 7 (only for premixing in sim)
0350   uint16_t packQIE8header(const HcalQIESample& qieSample, const HcalElectronicsId& eid, int flavor) {
0351     uint16_t header = 0;
0352 
0353     int fiber = eid.fiberIndex() + 1;
0354     int fiberchan = eid.fiberChanId();
0355 
0356     header |= (fiberchan & QIE8HeaderSpec::MASK_FIBERCHAN) << QIE8HeaderSpec::OFFSET_FIBERCHAN;
0357     header |= ((fiber - 1) & QIE8HeaderSpec::MASK_FIBER) << QIE8HeaderSpec::OFFSET_FIBER;
0358     if (flavor == 7) {
0359       header |= (15 & QIE8HeaderSpec::MASK_TECHNICAL_DATA_TYPE) << QIE8HeaderSpec::OFFSET_TECHNICAL_DATA_TYPE;
0360     } else {
0361       int fiberErr = qieSample.er();
0362       int capid0 = qieSample.capid();
0363       header |= (capid0 & QIE8HeaderSpec::MASK_CAPID) << QIE8HeaderSpec::OFFSET_CAPID;
0364       header |= (fiberErr & QIE8HeaderSpec::MASK_FIBERERR) << QIE8HeaderSpec::OFFSET_FIBERERR;
0365     }
0366     header |= (flavor & QIE8HeaderSpec::MASK_FLAVOR) << QIE8HeaderSpec::OFFSET_FLAVOR;  //flavor
0367     header |= (0x1 & QIE8HeaderSpec::MASK_HEADER_BIT) << QIE8HeaderSpec::OFFSET_HEADER_BIT;
0368 
0369     return header;
0370   }
0371 
0372   uint16_t packQIE8sample(const HcalQIESample& qieSample) {
0373     uint16_t sample = 0;
0374 
0375     int adc = qieSample.adc();
0376     int capid = qieSample.capid();
0377     int dv = qieSample.dv();
0378     int er = qieSample.er();
0379 
0380     sample |= (adc & QIE8SampleSpec::MASK_ADC) << QIE8SampleSpec::OFFSET_ADC;
0381     sample |= (capid & QIE8SampleSpec::MASK_CAPID) << QIE8SampleSpec::OFFSET_CAPID;
0382     sample |= (dv & QIE8SampleSpec::MASK_DV) << QIE8SampleSpec::OFFSET_DV;
0383     sample |= (er & QIE8SampleSpec::MASK_ER) << QIE8SampleSpec::OFFSET_ER;
0384 
0385     return sample;
0386   }
0387 
0388   uint16_t packTPheader(const HcalTriggerPrimitiveSample& tpSample, int channelid) {
0389     uint16_t header = 0;
0390 
0391     header |= (channelid & TPHeaderSpec::MASK_CHANID) << TPHeaderSpec::OFFSET_CHANID;
0392     header |= (0x0 & TPHeaderSpec::MASK_RESV) << TPHeaderSpec::OFFSET_RESV;
0393     header |= (0 & TPHeaderSpec::MASK_TPERR) << TPHeaderSpec::OFFSET_TPERR;
0394     header |= (0x4 & TPHeaderSpec::MASK_FLAVOR) << TPHeaderSpec::OFFSET_FLAVOR;  //flavor
0395     header |= (0x1 & TPHeaderSpec::MASK_HEADER_BIT) << TPHeaderSpec::OFFSET_HEADER_BIT;
0396 
0397     return header;
0398   }
0399 
0400   uint16_t packQIE10header(const HcalElectronicsId& eid) {
0401     uint16_t header = 0;
0402 
0403     int fiber = eid.fiberIndex();
0404     int fiberchan = eid.fiberChanId();
0405 
0406     header |= (fiberchan & QIE10HeaderSpec::MASK_FIBERCHAN) << QIE10HeaderSpec::OFFSET_FIBERCHAN;
0407     header |= (fiber & QIE10HeaderSpec::MASK_FIBER) << QIE10HeaderSpec::OFFSET_FIBER;
0408     header |= (0x0 & QIE10HeaderSpec::MASK_MP) << QIE10HeaderSpec::OFFSET_MP;
0409     header |= (0x0 & QIE10HeaderSpec::MASK_RESERV) << QIE10HeaderSpec::OFFSET_RESERV;
0410     header |= (0x0 & QIE10HeaderSpec::MASK_LE) << QIE10HeaderSpec::OFFSET_LE;
0411     header |= (0x2 & QIE10HeaderSpec::MASK_FLAVOR) << QIE10HeaderSpec::OFFSET_FLAVOR;  //flavor
0412     header |= (0x1 & QIE10HeaderSpec::MASK_HEADER_BIT) << QIE10HeaderSpec::OFFSET_HEADER_BIT;
0413 
0414     return header;
0415   }
0416 
0417   uint16_t packQIE11header(const QIE11DataFrame& qiedf, const HcalElectronicsId& eid) {
0418     uint16_t header = 0;
0419 
0420     int fiber = eid.fiberIndex();
0421     int fiberchan = eid.fiberChanId();
0422     int flavor = qiedf[0].flavor();
0423 
0424     if (flavor == 3) {
0425       header |= (fiberchan & QIE11HeaderSpec3::MASK_FIBERCHAN) << QIE11HeaderSpec3::OFFSET_FIBERCHAN;
0426       header |= (fiber & QIE11HeaderSpec3::MASK_FIBER) << QIE11HeaderSpec3::OFFSET_FIBER;
0427       header |= (0x0 & QIE11HeaderSpec3::MASK_MP) << QIE11HeaderSpec3::OFFSET_MP;
0428       header |= (0x0 & QIE11HeaderSpec3::MASK_LINKERROR) << QIE11HeaderSpec3::OFFSET_LINKERROR;
0429       header |= (flavor & QIE11HeaderSpec3::MASK_FLAVOR) << QIE11HeaderSpec3::OFFSET_FLAVOR;  //flavor
0430       header |= (0x1 & QIE11HeaderSpec3::MASK_HEADER_BIT) << QIE11HeaderSpec3::OFFSET_HEADER_BIT;
0431     } else {
0432       int capid0 = qiedf[0].capid();
0433       header |= (fiberchan & QIE11HeaderSpec0::MASK_FIBERCHAN) << QIE11HeaderSpec0::OFFSET_FIBERCHAN;
0434       header |= (fiber & QIE11HeaderSpec0::MASK_FIBER) << QIE11HeaderSpec0::OFFSET_FIBER;
0435       header |= (capid0 & QIE11HeaderSpec0::MASK_CAPID) << QIE11HeaderSpec0::OFFSET_CAPID;
0436       header |= (0x0 & QIE11HeaderSpec0::MASK_FIBERERR) << QIE11HeaderSpec0::OFFSET_FIBERERR;
0437       header |= (flavor & QIE11HeaderSpec0::MASK_FLAVOR) << QIE11HeaderSpec0::OFFSET_FLAVOR;  //flavor
0438       header |= (0x1 & QIE11HeaderSpec0::MASK_HEADER_BIT) << QIE11HeaderSpec0::OFFSET_HEADER_BIT;
0439     }
0440 
0441     return header;
0442   }
0443 
0444   uhtrData* newUHTR(int uhtrIndex, int ps = 0, int orn = 0, int bcn = 0, uint64_t evt = 0) {
0445     // initialize vector of 16-bit words
0446     uhtrs[uhtrIndex] = uhtrData(8);
0447     // build header -- some information will be updated at the end
0448 
0449     uint64_t presamples = std::max(ps, 0);
0450     uint64_t uhtrCrate = uhtrIndex & 0xFF;
0451     uint64_t uhtrSlot = (uhtrIndex & 0xF00) >> 8;
0452     // From Jeremy:
0453     // Set the firmware to zero, the firmware flavor to 0, the payload format to 1, and the event type to 1.
0454     uint64_t fwFlavor = 0;
0455     uint64_t eventType = 1;
0456     uint64_t payloadFormat = 1;
0457     uint64_t fwVersion = 0;
0458 
0459     uint64_t uhtrHeader1 = 0;
0460     uhtrHeader1 |= (uint64_t(0x0) & MASK_DATA_LENGTH) << OFFSET_DATA_LENGTH;
0461     uhtrHeader1 |= (bcn & MASK_BCN) << OFFSET_BCN;
0462     uhtrHeader1 |= (evt & MASK_EVN) << OFFSET_EVN;
0463     uhtrHeader1 |= (uint64_t(0x0) & MASK_FILED_BY_AMC13) << OFFSET_FILED_BY_AMC13;
0464 
0465     uint64_t uhtrHeader2 = 0;
0466     uhtrHeader2 |= (uhtrCrate & MASK_CRATE_ID) << OFFSET_CRATE_ID;
0467     uhtrHeader2 |= (uhtrSlot & MASK_SLOT_ID) << OFFSET_SLOT_ID;
0468     uhtrHeader2 |= (presamples & MASK_PRESAMPLES) << OFFSET_PRESAMPLES;
0469     uhtrHeader2 |= (orn & MASK_ORN) << OFFSET_ORN;
0470     uhtrHeader2 |= (fwFlavor & MASK_FW_FLAVOR) << OFFSET_FW_FLAVOR;
0471     uhtrHeader2 |= (eventType & MASK_EVENT_TYPE) << OFFSET_EVENT_TYPE;
0472     uhtrHeader2 |= (payloadFormat & MASK_PAYLOAD_FORMAT) << OFFSET_PAYLOAD_FORMAT;
0473     uhtrHeader2 |= (fwVersion & MASK_FW_VERSION) << OFFSET_FW_VERSION;
0474 
0475     // push header into vector of 16-bit words
0476     for (unsigned int i = 0; i < 4; ++i) {
0477       uhtrs[uhtrIndex][i] = (uhtrHeader1 >> (i * 16)) & 0xFFFF;
0478       uhtrs[uhtrIndex][i + 4] = (uhtrHeader2 >> (i * 16)) & 0xFFFF;
0479     }
0480 
0481     return &(uhtrs[uhtrIndex]);
0482   };
0483 
0484   void finalizeHeadTail(uhtrData* uhtr, bool verbosity) {
0485     uint64_t uhtr_size = uhtr->size() - 8;
0486 
0487     // adjust the size bits
0488     uhtr->at(0) = uhtr_size & 0xFFFF;
0489     uhtr->at(1) |= (uhtr_size >> 16) & 0xF;
0490 
0491     unsigned int toAdd = 4 - uhtr->size() % 4;
0492     for (unsigned int ia = 0; ia < toAdd; ia++) {
0493       uhtr->push_back(0xD07F);
0494     }
0495 
0496     // add trailer
0497     uhtr->push_back(uhtr_size & 0xFFFF);
0498     uhtr->push_back((uhtr_size >> 16) & 0xF);
0499     // this is ignoring the event number... I am not sure what this should be
0500 
0501     // adding some blank stuff for the CRC bits
0502     uhtr->push_back(0);
0503     uhtr->push_back(0);
0504   };
0505 
0506   void addChannel(int uhtrIndex,
0507                   edm::SortedCollection<HFDataFrame>::const_iterator& qiedf,
0508                   const HcalElectronicsMap* readoutMap,
0509                   bool premix,
0510                   int verbosity = 0) {
0511     if (qiedf->size() == 0)
0512       return;
0513     DetId detid = qiedf->id();
0514     HcalElectronicsId eid(readoutMap->lookup(detid));
0515     uint16_t header = packQIE8header(qiedf->sample(0), eid, premix ? 7 : 5);
0516     uhtrs[uhtrIndex].push_back(header);
0517     // loop over words in dataframe
0518     if (premix) {
0519       for (int iTS = 0; iTS < qiedf->size(); ++iTS) {
0520         uhtrs[uhtrIndex].push_back(packQIE8sample(qiedf->sample(iTS)));
0521       }
0522     } else {
0523       for (int iTS = 0; iTS < qiedf->size(); iTS += 2) {
0524         uint16_t cont = 0;
0525         int adc0 = qiedf->sample(iTS).adc();
0526         int adc1 = qiedf->sample(iTS + 1).adc();
0527         cont |= adc0 & 0xFF;
0528         cont |= (adc1 & 0xFF) << 8;
0529         uhtrs[uhtrIndex].push_back(cont);
0530       }
0531     }  // end loop over dataframe words
0532   };
0533 
0534   void addChannel(int uhtrIndex,
0535                   edm::SortedCollection<HBHEDataFrame>::const_iterator qiedf,
0536                   const HcalElectronicsMap* readoutMap,
0537                   bool premix,
0538                   int verbosity = 0) {
0539     if (qiedf->size() == 0)
0540       return;
0541     DetId detid = qiedf->id();
0542     HcalElectronicsId eid(readoutMap->lookup(detid));
0543     uint16_t header = packQIE8header(qiedf->sample(0), eid, premix ? 7 : 5);
0544     uhtrs[uhtrIndex].push_back(header);
0545     // loop over words in dataframe
0546     if (premix) {
0547       for (int iTS = 0; iTS < qiedf->size(); ++iTS) {
0548         uhtrs[uhtrIndex].push_back(packQIE8sample(qiedf->sample(iTS)));
0549       }
0550     } else {
0551       for (int iTS = 0; iTS < qiedf->size(); iTS += 2) {
0552         uint16_t cont = 0;
0553         int adc0 = qiedf->sample(iTS).adc();
0554         int adc1 = qiedf->sample(iTS + 1).adc();
0555         cont |= adc0 & 0xFF;
0556         cont |= (adc1 & 0xFF) << 8;
0557         uhtrs[uhtrIndex].push_back(cont);
0558       }
0559     }  // end loop over dataframe words
0560   };
0561 
0562   void addChannel(int uhtrIndex,
0563                   edm::SortedCollection<HcalTriggerPrimitiveDigi>::const_iterator qiedf,
0564                   int channelid,
0565                   int verbosity = 0) {
0566     if (qiedf->size() == 0)
0567       return;
0568     uint16_t header = packTPheader(qiedf->sample(0), channelid);
0569     uhtrs[uhtrIndex].push_back(header);
0570     // loop over words in dataframe
0571     for (int iTS = 0; iTS < qiedf->size(); iTS++) {
0572       // push data into uhtr data container
0573       auto raw = qiedf->sample(iTS).raw();
0574       // Add SOI information
0575       if (iTS == qiedf->presamples())
0576         raw |= TPHeaderSpec::MASK_SOI_BIT << TPHeaderSpec::OFFSET_SOI_BIT;
0577       uhtrs[uhtrIndex].push_back(raw);
0578     }  // end loop over dataframe words
0579   };
0580 
0581   void addChannel(int uhtrIndex, QIE11DataFrame qiedf, const HcalElectronicsMap* readoutMap, int verbosity = 0) {
0582     DetId detid = qiedf.detid();
0583     HcalElectronicsId eid(readoutMap->lookup(detid));
0584     // loop over words in dataframe
0585     for (edm::DataFrame::iterator dfi = qiedf.begin(); dfi != qiedf.end(); ++dfi) {
0586       if (dfi >= qiedf.end() - QIE11DataFrame::FLAG_WORDS) {
0587         continue;
0588       }
0589       if (dfi == qiedf.begin() && QIE11DataFrame::HEADER_WORDS == 1) {
0590         uint16_t header = packQIE11header(qiedf, eid);
0591         uhtrs[uhtrIndex].push_back(header);
0592         continue;
0593       }
0594       // push data into uhtr data container
0595       uhtrs[uhtrIndex].push_back(dfi[0]);
0596     }  // end loop over dataframe words
0597   };
0598 
0599   void addChannel(int uhtrIndex, QIE10DataFrame qiedf, const HcalElectronicsMap* readoutMap, int verbosity = 0) {
0600     DetId detid = qiedf.detid();
0601     HcalElectronicsId eid(readoutMap->lookup(detid));
0602     // loop over words in dataframe
0603     for (edm::DataFrame::iterator dfi = qiedf.begin(); dfi != qiedf.end(); ++dfi) {
0604       if (dfi >= qiedf.end() - QIE10DataFrame::FLAG_WORDS) {
0605         continue;
0606       }
0607       if (dfi == qiedf.begin() && QIE10DataFrame::HEADER_WORDS == 1) {
0608         uint16_t header = packQIE10header(eid);
0609         uhtrs[uhtrIndex].push_back(header);
0610         continue;
0611       }
0612       // push data into uhtr data container
0613       uhtrs[uhtrIndex].push_back(dfi[0]);
0614     }  // end loop over dataframe words
0615   };
0616 };
0617 
0618 // converts HE QIE digies to HB data format
0619 
0620 inline QIE11DataFrame convertHB(QIE11DataFrame qiehe,
0621                                 std::vector<int> const& tdc1,
0622                                 std::vector<int> const& tdc2,
0623                                 const int tdcmax) {
0624   QIE11DataFrame qiehb = qiehe;
0625   HcalDetId did = HcalDetId(qiehb.detid());
0626   int adc, tdc;
0627   bool soi;
0628   int is = 0;
0629   int capid = qiehe[0].capid();
0630   //  flavor for HB digies is hardcoded here
0631   static const int hbflavor = 3;
0632   //  maximum HB depth
0633   static const int maxHBdepth = 4;
0634 
0635   const int entry = (abs(did.ieta()) - 1) * maxHBdepth + did.depth() - 1;
0636   const int first = tdc1.at(entry);
0637   const int second = tdc2.at(entry);
0638 
0639   //  iterator over samples
0640   for (edm::DataFrame::const_iterator it = qiehe.begin(); it != qiehe.end(); ++it) {
0641     if (it == qiehe.begin())
0642       continue;
0643     adc = qiehe[is].adc();
0644     tdc = qiehe[is].tdc();
0645     soi = qiehe[is].soi();
0646 
0647     if (tdc >= 0 && tdc <= first)
0648       tdc = 0;
0649     else if (tdc > first && tdc <= second)
0650       tdc = 1;
0651     else if (tdc > second && tdc <= tdcmax)
0652       tdc = 2;
0653     else
0654       tdc = 3;
0655 
0656     qiehb.setSample(is, adc, tdc, soi);
0657     is++;
0658   };
0659 
0660   // puting flavor is safe here because flavor is stored in the same bits for all flavors
0661   qiehb.setFlavor(hbflavor);
0662   qiehb.setCapid0(capid);
0663 
0664   return qiehb;
0665 }
0666 
0667 #endif