00001 #include "EventFilter/HcalRawToDigi/interface/HcalPacker.h"
00002 #include "EventFilter/HcalRawToDigi/interface/HcalHTRData.h"
00003 #include "EventFilter/HcalRawToDigi/interface/HcalDCCHeader.h"
00004 #include "DataFormats/HcalDetId/interface/HcalGenericDetId.h"
00005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00006 #include "DataFormats/FEDRawData/interface/FEDTrailer.h"
00007 #include "FWCore/Utilities/interface/CRC16.h"
00008
00009 HcalPacker::Collections::Collections() {
00010 hbhe=0;
00011 hoCont=0;
00012 hfCont=0;
00013 tpCont=0;
00014 zdcCont=0;
00015 calibCont=0;
00016 }
00017
00018 template <class Coll, class DetIdClass>
00019 int process(const Coll* pt, const DetId& did, unsigned short* buffer, int& presamples,bool& isUS, bool& isMP) {
00020 isUS=false; isMP=false;
00021 if (pt==0) return 0;
00022 int size=0;
00023 typename Coll::const_iterator i=pt->find(DetIdClass(did));
00024 if (i!=pt->end()) {
00025 isUS=i->zsUnsuppressed();
00026 isMP=i->zsMarkAndPass();
00027 presamples=i->presamples();
00028 size=i->size();
00029 for (int j=0; j<size; j++)
00030 buffer[j]=(*i)[j].raw();
00031 }
00032 return size;
00033 }
00034
00035 static unsigned char processTrig(const HcalTrigPrimDigiCollection* pt, const HcalTrigTowerDetId& tid, unsigned short* buffer) {
00036 if (pt==0) return 0;
00037 int size=0;
00038 HcalTrigPrimDigiCollection::const_iterator i=pt->find(tid);
00039 if (i!=pt->end()) {
00040 int presamples=i->presamples();
00041 int samples=i->size();
00042
00043 for (int j=0; j<samples; j++) {
00044 buffer[j]=(*i)[j].raw();
00045 if (j==presamples) buffer[j]|=0x0200;
00046 }
00047 }
00048 return size;
00049 }
00050
00051 int HcalPacker::findSamples(const DetId& did, const Collections& inputs,
00052 unsigned short* buffer, int &presamples, bool& isUS, bool& isMP) {
00053 if (!(did.det()==DetId::Hcal || (did.det()== DetId::Calo && did.subdetId()==HcalZDCDetId::SubdetectorId)) ) return 0;
00054 int size=0;
00055 HcalGenericDetId genId(did);
00056
00057 switch (genId.genericSubdet()) {
00058 case(HcalGenericDetId::HcalGenBarrel):
00059 case(HcalGenericDetId::HcalGenEndcap):
00060 size=process<HBHEDigiCollection,HcalDetId>(inputs.hbhe,did,buffer,presamples,isUS,isMP);
00061 break;
00062 case(HcalGenericDetId::HcalGenOuter):
00063 size=process<HODigiCollection,HcalDetId>(inputs.hoCont,did,buffer,presamples,isUS,isMP);
00064 break;
00065 case(HcalGenericDetId::HcalGenForward):
00066 size=process<HFDigiCollection,HcalDetId>(inputs.hfCont,did,buffer,presamples,isUS,isMP);
00067 break;
00068 case(HcalGenericDetId::HcalGenZDC):
00069 size=process<ZDCDigiCollection,HcalZDCDetId>(inputs.zdcCont,did,buffer,presamples,isUS,isMP);
00070 break;
00071 case(HcalGenericDetId::HcalGenCalibration):
00072 size=process<HcalCalibDigiCollection,HcalCalibDetId>(inputs.calibCont,did,buffer,presamples,isUS,isMP);
00073 break;
00074 default: size=0;
00075 }
00076 return size;
00077 }
00078
00079 void HcalPacker::pack(int fedid, int dccnumber,
00080 int nl1a, int orbitn, int bcn,
00081 const Collections& inputs,
00082 const HcalElectronicsMap& emap,
00083 FEDRawData& output) {
00084 std::vector<unsigned short> precdata(HcalHTRData::CHANNELS_PER_SPIGOT*HcalHTRData::MAXIMUM_SAMPLES_PER_CHANNEL);
00085 std::vector<unsigned short> trigdata(HcalHTRData::CHANNELS_PER_SPIGOT*HcalHTRData::MAXIMUM_SAMPLES_PER_CHANNEL);
00086 std::vector<unsigned char> preclen(HcalHTRData::CHANNELS_PER_SPIGOT);
00087 std::vector<unsigned char> triglen(HcalHTRData::CHANNELS_PER_SPIGOT);
00088 static const int HTRFormatVersion=5;
00089 bool channelIsMP[HcalHTRData::CHANNELS_PER_SPIGOT];
00090
00091 HcalHTRData spigots[15];
00092
00093 for (int spigot=0; spigot<15; spigot++) {
00094 spigots[spigot].allocate(HTRFormatVersion);
00095 HcalElectronicsId exampleEId;
00096 int npresent=0;
00097 int presamples=-1, samples=-1;
00098 bool haveUnsuppressed=false;
00099 for (int fiber=1; fiber<=8; fiber++)
00100 for (int fiberchan=0; fiberchan<3; fiberchan++) {
00101 int linear=(fiber-1)*3+fiberchan;
00102 HcalQIESample chanSample(0,0,fiber,fiberchan,false,false);
00103 unsigned short chanid=chanSample.raw()&0xF800;
00104 preclen[linear]=0;
00105 channelIsMP[linear]=false;
00106
00107 HcalElectronicsId partialEid(fiberchan,fiber,spigot,dccnumber);
00108
00109 HcalElectronicsId fullEid;
00110 HcalGenericDetId genId;
00111 if (!emap.lookup(partialEid,fullEid,genId)) continue;
00112
00113
00114
00115 unsigned short* database=&(precdata[linear*HcalHTRData::MAXIMUM_SAMPLES_PER_CHANNEL]);
00116 int mypresamples=-1;
00117 bool isUS=false, isMP=false;
00118 int mysamples=findSamples(genId,inputs,database,mypresamples,isUS,isMP);
00119 haveUnsuppressed=haveUnsuppressed || isUS;
00120 channelIsMP[linear]=isMP;
00121
00122 if (mysamples>0) {
00123 if (samples<0) samples=mysamples;
00124 else if (samples!=mysamples) {
00125 edm::LogError("HCAL") << "Mismatch of samples in a single HTR (unsupported) " << mysamples << " != " << samples;
00126 continue;
00127 }
00128 if (presamples<0) {
00129 presamples=mypresamples;
00130 exampleEId=fullEid;
00131 } else if (mypresamples!=presamples) {
00132 edm::LogError("HCAL") << "Mismatch of presamples in a single HTR (unsupported) " << mypresamples << " != " << presamples;
00133 continue;
00134 }
00135 for (int ii=0; ii<samples; ii++)
00136 database[ii]=(database[ii]&0x7FF)|chanid;
00137 preclen[linear]=(unsigned char)(samples);
00138 npresent++;
00139 }
00140 }
00141 for (int slb=1; slb<=6; slb++)
00142 for (int slbchan=0; slbchan<=3; slbchan++) {
00143 int linear=(slb-1)*4+slbchan;
00144 HcalTriggerPrimitiveSample idCvt(0,0,slb,slbchan);
00145 unsigned short chanid=idCvt.raw()&0xF800;
00146 triglen[linear]=0;
00147
00148 HcalElectronicsId partialEid(slbchan,slb,spigot,dccnumber,0,0,0);
00149
00150 HcalElectronicsId fullEid;
00151 HcalTrigTowerDetId tid;
00152 if (!emap.lookup(partialEid,fullEid,tid)) {
00153
00154 continue;
00155 }
00156
00157
00158 if (!tid.null()) {
00159 unsigned short* trigbase=&(trigdata[linear*HcalHTRData::MAXIMUM_SAMPLES_PER_CHANNEL]);
00160 triglen[linear]=processTrig(inputs.tpCont,tid,trigbase);
00161
00162 for (unsigned char q=0; q<triglen[linear]; q++)
00163 trigbase[q]=(trigbase[q]&0x7FF)|chanid;
00164 }
00165 }
00167 if (npresent>0) {
00168 spigots[spigot].pack(&(preclen[0]),&(precdata[0]),
00169 &(triglen[0]),&(trigdata[0]),
00170 false);
00171 static const int pipeline=0x22;
00172 static const int firmwareRev=0;
00173 int submodule=exampleEId.htrTopBottom()&0x1;
00174 submodule|=(exampleEId.htrSlot()&0x1F)<<1;
00175 submodule|=(exampleEId.readoutVMECrateId()&0x1f)<<6;
00176 spigots[spigot].packHeaderTrailer(nl1a,
00177 bcn,
00178 submodule,
00179 orbitn,
00180 pipeline,
00181 samples,
00182 presamples,
00183 firmwareRev);
00184 if (haveUnsuppressed) {
00185 spigots[spigot].packUnsuppressed(channelIsMP);
00186 }
00187
00188 }
00189 }
00190
00191 int theSize=0;
00192 for (int spigot=0; spigot<15; spigot++) {
00193 theSize+=spigots[spigot].getRawLength()*sizeof(unsigned short);
00194 }
00195 theSize+=sizeof(HcalDCCHeader)+8;
00196 theSize+=(8-(theSize%8))%8;
00197 output.resize(theSize);
00198
00199
00200 HcalDCCHeader* dcc=(HcalDCCHeader*)(output.data());
00201 dcc->clear();
00202 dcc->setHeader(fedid,bcn,nl1a,orbitn);
00203
00204
00205 for (int spigot=0; spigot<15; spigot++) {
00206 if (spigots[spigot].getRawLength()>0)
00207 dcc->copySpigotData(spigot,spigots[spigot],true,0);
00208 }
00209
00210 FEDTrailer fedTrailer(output.data()+(output.size()-8));
00211 fedTrailer.set(output.data()+(output.size()-8),
00212 output.size()/8,
00213 evf::compute_crc(output.data(),output.size()), 0, 0);
00214 }