Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 //#include "Utilities/Configuration/interface/Architecture.h"
0002 /*  
0003  *  \author J. Mans -- UMD
0004  */
0005 #ifndef HTBDAQ_DATA_STANDALONE
0006 #include "EventFilter/HcalRawToDigi/interface/HcalHTRData.h"
0007 #else
0008 #include "HcalHTRData.h"
0009 const int HcalHTRData::CHANNELS_PER_SPIGOT = 24;
0010 const int HcalHTRData::MAXIMUM_SAMPLES_PER_CHANNEL = 20;
0011 #endif
0012 #include <cstring>
0013 #include <cstdio>
0014 
0015 HcalHTRData::HcalHTRData() : m_formatVersion(-2), m_rawLength(0), m_rawConst(nullptr), m_ownData(nullptr) {}
0016 HcalHTRData::HcalHTRData(const unsigned short* data, int length) {
0017   adoptData(data, length);
0018   m_ownData = nullptr;
0019 }
0020 HcalHTRData::HcalHTRData(const HcalHTRData& hd)
0021     : m_formatVersion(hd.m_formatVersion), m_rawLength(hd.m_rawLength), m_rawConst(hd.m_rawConst), m_ownData(nullptr) {}
0022 
0023 HcalHTRData::HcalHTRData(int version_to_create) : m_formatVersion(version_to_create) { allocate(version_to_create); }
0024 
0025 void HcalHTRData::allocate(int version_to_create) {
0026   m_formatVersion = version_to_create;
0027   // the needed space is for the biggest possible event...
0028   const int needed = 0x200;
0029   // create a buffer big enough...
0030   m_ownData = new unsigned short[needed];
0031   // clear isn't really necessary, but it makes valgrind happy
0032   memset(m_ownData, 0, sizeof(unsigned short) * needed);
0033   m_rawLength = 0;
0034   m_rawConst = m_ownData;
0035 }
0036 
0037 HcalHTRData& HcalHTRData::operator=(const HcalHTRData& hd) {
0038   if (m_ownData == nullptr) {
0039     m_formatVersion = hd.m_formatVersion;
0040     m_rawLength = hd.m_rawLength;
0041     m_rawConst = hd.m_rawConst;
0042   }
0043   return (*this);
0044 }
0045 
0046 void HcalHTRData::adoptData(const unsigned short* data, int length) {
0047   m_rawLength = length;
0048   m_rawConst = data;
0049   if (m_rawLength < 5) {
0050     m_formatVersion = -2;  // invalid!
0051   } else {
0052     // determine format version
0053     if ((m_rawConst[2] & 0x8000) == 0)
0054       m_formatVersion = -1;  // original format before versions
0055     else
0056       m_formatVersion = (m_rawConst[4] >> 12) & 0xF;
0057   }
0058 }
0059 
0060 // check :: not EE, length is reasonable, length matches wordcount
0061 //          length required for tp+daq is correct
0062 
0063 bool HcalHTRData::check() const {
0064   if (m_formatVersion == -1) {
0065     // length checks
0066     //  minimum length
0067     if (m_rawLength < 6 + 12)
0068       return false;
0069     //  matches wordcount
0070     if (m_rawLength != m_rawConst[m_rawLength - 3])
0071       return false;
0072     // empty event check
0073     if (m_rawConst[2] & 0x20)
0074       return false;
0075   } else {
0076     // length checks
0077     //  minimum length
0078     if (m_rawLength < 8 + 4)
0079       return false;
0080     if (m_formatVersion <= 3) {
0081       //  matches wordcount
0082       if (m_rawLength != m_rawConst[m_rawLength - 3]) {
0083         if (isHistogramEvent() && m_rawConst[m_rawLength - 3] == 786) {
0084           // known bug!
0085         } else
0086           return false;
0087       }
0088     } else {
0089       // eventually add CRC check
0090     }
0091     // empty event check (redundant...)
0092     if (m_rawConst[2] & 0x4)
0093       return false;
0094   }
0095 
0096   if (!isHistogramEvent()) {
0097     // daq/tp length check
0098     int tp, daq, header, trailer;
0099     determineSectionLengths(tp, daq, header, trailer);
0100     if (tp + daq + header + trailer > m_rawLength)
0101       return false;
0102   }
0103 
0104   return true;
0105 }
0106 
0107 bool HcalHTRData::isEmptyEvent() const {
0108   if (m_formatVersion == -1) {
0109     return (m_rawConst[2] & 0x20) != 0;
0110   } else {
0111     return (m_rawConst[2] & 0x4) != 0;
0112   }
0113 }
0114 
0115 bool HcalHTRData::isOverflowWarning() const {
0116   if (m_formatVersion == -1) {
0117     return false;  // too old to care.
0118   } else {
0119     return (m_rawConst[2] & 0x1) != 0;
0120   }
0121 }
0122 
0123 bool HcalHTRData::isBusy() const {
0124   if (m_formatVersion == -1) {
0125     return false;  // too old to care.
0126   } else {
0127     return (m_rawConst[2] & 0x2) != 0;
0128   }
0129 }
0130 
0131 void HcalHTRData::determineSectionLengths(int& tpWords, int& daqWords, int& headerWords, int& trailerWords) const {
0132   if (m_formatVersion == -1) {
0133     tpWords = m_rawConst[5] >> 8;
0134     daqWords = CHANNELS_PER_SPIGOT * (m_rawConst[m_rawLength - 4] >> 8);  // always 24 channels, no zero suppresion
0135     headerWords = 6;
0136     trailerWords = 12;
0137   } else {
0138     tpWords = m_rawConst[5] >> 8;
0139     if (m_rawLength > 4)
0140       daqWords = m_rawConst[m_rawLength - 4] & 0x7FF;  // zero suppression supported
0141     else
0142       daqWords = 0;  //should there be a warning as well?
0143     headerWords = 8;
0144     trailerWords = 4;  // minimum, may be more...
0145   }
0146 }
0147 
0148 void HcalHTRData::determineStaticLengths(int& headerWords, int& trailerWords) const {
0149   if (m_formatVersion == -1) {
0150     headerWords = 6;
0151     trailerWords = 12;
0152   } else if (m_formatVersion < 5) {
0153     headerWords = 8;
0154     trailerWords = 4;  // minimum, may be more...
0155   } else {
0156     headerWords = 8;
0157     trailerWords = 12;  // minimum, may be more...
0158   }
0159 }
0160 
0161 void HcalHTRData::dataPointers(const unsigned short** daq_first,
0162                                const unsigned short** daq_last,
0163                                const unsigned short** tp_first,
0164                                const unsigned short** tp_last) const {
0165   int tp_words_total, daq_words_total, headerLen, trailerLen;
0166   determineSectionLengths(tp_words_total, daq_words_total, headerLen, trailerLen);
0167 
0168   *tp_first = m_rawConst + headerLen;
0169   *tp_last = *tp_first + (tp_words_total - 1);
0170   *daq_first = *tp_last + 1;
0171   *daq_last = *daq_first + (daq_words_total - 1);
0172 }
0173 
0174 /* using FiberAd[2:0] ChanId[1:0] */
0175 static const int channelDecoder[32] = {0,  1,  2,  99, 3,  4,  5,  99, 6,  7,  8,  99, 9,  10, 11, 99,
0176                                        12, 13, 14, 99, 15, 16, 17, 99, 18, 19, 20, 99, 21, 22, 23, 99};
0177 
0178 void HcalHTRData::unpack(unsigned char* daq_lengths,
0179                          unsigned short* daq_samples,
0180                          unsigned char* tp_lengths,
0181                          unsigned short* tp_samples) const {
0182   if (daq_lengths != nullptr)
0183     memset(daq_lengths, 0, CHANNELS_PER_SPIGOT);
0184   if (tp_lengths != nullptr)
0185     memset(tp_lengths, 0, CHANNELS_PER_SPIGOT);
0186 
0187   // currently, the major differences between the versions are
0188   //  -1 : 6 word header, no zero suppression, trailer setup
0189   //   0 : 8 word header, zero suppression,
0190 
0191   int tp_words_total, daq_words_total, headerLen, trailerLen;
0192   determineSectionLengths(tp_words_total, daq_words_total, headerLen, trailerLen);
0193 
0194   //  printf("%d %d %d %d\n",tp_words_total,daq_words_total,headerLen,trailerLen);
0195   int wordPtr;
0196   const unsigned short* tpBase = m_rawConst + headerLen;
0197   // process the trigger primitive words
0198   if (tp_lengths != nullptr) {
0199     for (wordPtr = 0; wordPtr < tp_words_total; wordPtr++) {
0200       int ichan = channelDecoder[tpBase[wordPtr] >> 11];
0201       if (ichan >= 24)
0202         continue;
0203       tp_samples[ichan * MAXIMUM_SAMPLES_PER_CHANNEL + tp_lengths[ichan]] = tpBase[wordPtr] & 0x3ff;
0204       tp_lengths[ichan]++;
0205     }
0206   }
0207 
0208   const unsigned short* daqBase = m_rawConst + headerLen + tp_words_total;
0209   // process the DAQ words [ assumes that data from one channel will always be together ]
0210   int lastChan = -1;
0211   int lastCapid = 0;
0212   if (daq_lengths != nullptr) {
0213     for (wordPtr = 0; wordPtr < daq_words_total; wordPtr++) {
0214       int ichan = channelDecoder[daqBase[wordPtr] >> 11];
0215       if (ichan >= 24)
0216         continue;
0217       int capid = (daqBase[wordPtr] & 0x180) >> 7;
0218       int erdv = (daqBase[wordPtr] & 0x600) >> 9;
0219       if (erdv != 0x1 || (lastChan == ichan && (capid != ((lastCapid + 1) % 4)))) {
0220         daq_lengths[ichan] |= 0x80;
0221       }
0222       lastChan = ichan;
0223       lastCapid = capid;
0224 
0225       int useLength = daq_lengths[ichan] & 0x1F;
0226       //     printf("%d %d\n",ichan,useLength);
0227       daq_samples[ichan * MAXIMUM_SAMPLES_PER_CHANNEL + useLength] = daqBase[wordPtr] & 0x3ff;
0228       daq_lengths[ichan] = (useLength + 1) | (daq_lengths[ichan] & 0xE0);  // keep the error bits
0229     }
0230   }
0231 }
0232 
0233 void HcalHTRData::pack(unsigned char* daq_lengths,
0234                        unsigned short* daq_samples,
0235                        unsigned char* tp_lengths,
0236                        unsigned short* tp_samples,
0237                        bool do_capid) {
0238   int tp_words_total = 0, daq_words_total = 0, headerLen, trailerLen;
0239   determineStaticLengths(headerLen, trailerLen);
0240 
0241   tp_words_total = 0;
0242   daq_words_total = 0;
0243   int ichan, isample;
0244 
0245   // trigger primitive words
0246   unsigned short* ptr = m_ownData + headerLen;
0247   if (tp_samples != nullptr && tp_lengths != nullptr) {
0248     for (ichan = 0; ichan < 24; ichan++) {
0249       unsigned short chanid = ((ichan % 4) + (((ichan / 4) + 1) << 2)) << 11;
0250       for (isample = 0; isample < tp_lengths[ichan] && isample < MAXIMUM_SAMPLES_PER_CHANNEL; isample++) {
0251         ptr[tp_words_total] = chanid | (tp_samples[ichan * MAXIMUM_SAMPLES_PER_CHANNEL + isample] & 0x3FF);
0252         tp_words_total++;
0253       }
0254     }
0255   }
0256 
0257   // daq words
0258   ptr = m_ownData + headerLen + tp_words_total;
0259   for (ichan = 0; ichan < 24; ichan++) {
0260     unsigned short chanid = ((ichan % 3) + ((ichan / 3) << 2)) << 11;
0261     for (isample = 0; isample < daq_lengths[ichan] && isample < MAXIMUM_SAMPLES_PER_CHANNEL; isample++) {
0262       unsigned short basedata = daq_samples[ichan * MAXIMUM_SAMPLES_PER_CHANNEL + isample] & 0x7FF;
0263       if (do_capid)
0264         basedata = (basedata & 0x7F) | (0x200) | ((isample % 4) << 7);
0265       ptr[daq_words_total] = chanid | basedata;
0266       daq_words_total++;
0267     }
0268   }
0269   unsigned short totalLen;
0270   if (m_formatVersion == -1) {
0271     m_ownData[5] = (tp_words_total << 8) | 0x1;
0272     totalLen = headerLen + tp_words_total + daq_words_total + trailerLen;
0273     m_rawLength = totalLen;
0274     m_ownData[totalLen - 3] = totalLen;
0275     m_ownData[totalLen - 4] = (tp_words_total / CHANNELS_PER_SPIGOT) | ((daq_words_total / CHANNELS_PER_SPIGOT) << 8);
0276   } else {
0277     m_ownData[5] = (tp_words_total << 8) | 0x1;
0278     totalLen = headerLen + tp_words_total + daq_words_total + trailerLen;
0279     if ((totalLen % 2) == 1) {
0280       m_ownData[totalLen - 4] = 0xFFFF;  // parity word
0281       totalLen++;                        // round to even number of 16-bit words
0282     }
0283     m_rawLength = totalLen;
0284     m_ownData[totalLen - 2] = totalLen / 2;  // 32-bit words
0285     m_ownData[totalLen - 3] = totalLen;
0286     m_ownData[totalLen - 4] = daq_words_total;
0287   }
0288   if (trailerLen == 12) {  // initialize extra trailer words if present
0289     for (int i = 12; i > 4; i--)
0290       m_ownData[totalLen - i] = 0;
0291   }
0292 }
0293 
0294 void HcalHTRData::packHeaderTrailer(int L1Anumber,
0295                                     int bcn,
0296                                     int submodule,
0297                                     int orbitn,
0298                                     int pipeline,
0299                                     int ndd,
0300                                     int nps,
0301                                     int firmwareRev,
0302                                     int firmwareFlav) {
0303   m_ownData[0] = L1Anumber & 0xFF;
0304   m_ownData[1] = (L1Anumber & 0xFFFF00) >> 8;
0305   if (m_formatVersion == -1) {
0306     m_ownData[2] = ((pipeline & 0x7F) << 8);  // no error bits
0307     m_ownData[3] = ((orbitn & 0xFF) << 8) | (submodule & 0xFF);
0308     m_ownData[4] = bcn & 0xFFF;
0309     //    m_ownData[5]&=0xFF01;
0310   } else {
0311     m_ownData[2] = 0x8000;  // Version is valid, no error bits
0312     if (m_formatVersion == 0)
0313       m_ownData[3] = ((orbitn & 0x3F) << 10) | (submodule & 0x3FF);
0314     else
0315       m_ownData[3] = ((orbitn & 0x1F) << 11) | (submodule & 0x7FF);
0316     m_ownData[4] = ((m_formatVersion & 0xF) << 12) | (bcn & 0xFFF);
0317     m_ownData[5] |= ((nps & 0x1F) << 3) | 0x1;
0318     m_ownData[6] = ((firmwareRev & 0x70000) >> 3) | (firmwareRev & 0x1FFF);
0319     m_ownData[7] = (pipeline & 0xFF) | ((firmwareFlav & 0x3F) << 8);
0320     m_ownData[m_rawLength - 4] &= 0x7FF;
0321     m_ownData[m_rawLength - 4] |= (ndd & 0x1F) << 11;
0322   }
0323   m_ownData[m_rawLength - 2] = m_rawLength / 2;  // 32-bit words
0324   m_ownData[m_rawLength - 1] = (L1Anumber & 0xFF) << 8;
0325 }
0326 
0327 void HcalHTRData::packUnsuppressed(const bool* mp) {
0328   if (m_formatVersion < 4)
0329     return;
0330 
0331   for (int fiber = 1; fiber <= 8; fiber++) {
0332     for (int fiberchan = 0; fiberchan <= 2; fiberchan++) {
0333       int linchan = (fiber - 1) * 3 + fiberchan;
0334 
0335       unsigned short& val = m_ownData[m_rawLength - 12 + (linchan / 8)];
0336       if (mp[linchan])
0337         val |= 1 << (linchan % 8);
0338     }
0339   }
0340 
0341   // set the unsupressed bit
0342   m_ownData[6] |= 0x8000;
0343 }
0344 
0345 unsigned int HcalHTRData::getOrbitNumber() const {
0346   switch (m_formatVersion) {
0347     case (-1):
0348       return (m_rawConst[3] >> 8);
0349     case (0):
0350       return (m_rawConst[3] >> 10);
0351     default:
0352       return (m_rawConst[3] >> 11);
0353   }
0354 }
0355 unsigned int HcalHTRData::getSubmodule() const {
0356   switch (m_formatVersion) {
0357     case (-1):
0358       return (m_rawConst[3] & 0xFF);
0359     case (0):
0360       return (m_rawConst[3] & 0x3FF);
0361     default:
0362       return (m_rawConst[3] & 0x7FF);
0363   }
0364 }
0365 unsigned int HcalHTRData::htrSlot() const {
0366   const unsigned int smid = getSubmodule();
0367   return ((smid >> 1) & 0x1F);
0368 }
0369 unsigned int HcalHTRData::htrTopBottom() const {
0370   const unsigned int smid = getSubmodule();
0371   return (smid & 0x01);
0372 }
0373 unsigned int HcalHTRData::readoutVMECrateId() const {
0374   const unsigned int smid = getSubmodule();
0375   return ((smid >> 6) & 0x1F);
0376 }
0377 bool HcalHTRData::isCalibrationStream() const { return (m_formatVersion == -1) ? (false) : (m_rawConst[2] & 0x4000); }
0378 bool HcalHTRData::isUnsuppressed() const { return (m_formatVersion < 4) ? (false) : (m_rawConst[6] & 0x8000); }
0379 bool HcalHTRData::wasMarkAndPassZS(int fiber, int fiberchan) const {
0380   if (fiber < 1 || fiber > 8 || fiberchan < 0 || fiberchan > 2)
0381     return false;
0382   if (!isUnsuppressed() || m_formatVersion < 5)
0383     return false;
0384   int linchan = (fiber - 1) * 3 + fiberchan;
0385 
0386   unsigned short val = m_rawConst[m_rawLength - 12 + (linchan / 8)];
0387   return ((val >> (linchan % 8)) & 0x1) != 0;
0388 }
0389 bool HcalHTRData::wasMarkAndPassZSTP(int slb, int slbchan) const {
0390   if (slb < 1 || slb > 6 || slbchan < 0 || slbchan > 3)
0391     return false;
0392   if (!isUnsuppressed() || m_formatVersion < 5)
0393     return false;
0394   int linchan = (slb - 1) * 4 + slbchan;
0395 
0396   unsigned short val = m_rawConst[m_rawLength - 12 + (linchan / 8)];
0397   return ((val >> (linchan % 8)) & 0x100) != 0;
0398 }
0399 
0400 uint32_t HcalHTRData::zsBunchMask() const {
0401   uint32_t mask = 0;
0402   if (isUnsuppressed() && m_formatVersion >= 5) {
0403     mask = m_rawConst[m_rawLength - 5] | ((m_rawConst[m_rawLength - 6] & 0xF000) << 4);
0404   }
0405   return mask;
0406 }
0407 
0408 bool HcalHTRData::isPatternRAMEvent() const { return (m_formatVersion == -1) ? (false) : (m_rawConst[2] & 0x1000); }
0409 bool HcalHTRData::isHistogramEvent() const {
0410   return (m_formatVersion == -1) ? (m_rawConst[2] & 0x2) : (m_rawConst[2] & 0x2000);
0411 }
0412 int HcalHTRData::getNDD() const {
0413   return (m_formatVersion == -1) ? (m_rawConst[m_rawLength - 4] >> 8) : (m_rawConst[m_rawLength - 4] >> 11);
0414 }
0415 int HcalHTRData::getNTP() const {
0416   int retval = -1;
0417   if (m_formatVersion == -1)
0418     retval = m_rawConst[m_rawLength - 4] & 0xFF;
0419   else if (m_formatVersion < 3)
0420     retval = m_rawConst[m_rawLength - 4] >> 11;
0421   return retval;
0422 }
0423 int HcalHTRData::getNPrecisionWords() const {
0424   return (m_formatVersion == -1) ? (m_rawConst[m_rawLength - 4] & 0xFF) : (m_rawConst[m_rawLength - 4] & 0x7FF);
0425 }
0426 int HcalHTRData::getNPS() const { return (m_formatVersion == -1) ? (0) : ((m_rawConst[5] >> 3) & 0x1F); }
0427 unsigned int HcalHTRData::getPipelineLength() const {
0428   return (m_formatVersion == -1) ? (m_rawConst[2] >> 8) : (m_rawConst[7] & 0xFF);
0429 }
0430 unsigned int HcalHTRData::getFirmwareRevision() const {
0431   return (m_formatVersion == -1) ? (0) : ((m_rawConst[6] & 0x1FFF) + ((m_rawConst[6] & 0xE000) << 3));
0432 }
0433 int HcalHTRData::getFirmwareFlavor() const { return (m_formatVersion < 2) ? (-1) : ((m_rawConst[7] >> 8) & 0xFF); }
0434 
0435 void HcalHTRData::getHistogramFibers(int& a, int& b) const {
0436   a = -1;
0437   b = -1;
0438   if (m_formatVersion == -1) {
0439     a = ((m_rawConst[2] & 0x0F00) >> 8);
0440     b = ((m_rawConst[2] & 0xF000) >> 12);
0441   } else {
0442     a = ((m_rawConst[5] & 0x0F00) >> 8) + 1;
0443     b = ((m_rawConst[5] & 0xF000) >> 12) + 1;
0444   }
0445 }
0446 
0447 bool HcalHTRData::wasHistogramError(int ifiber) const {
0448   bool retval = !isHistogramEvent();
0449   if (!retval) {
0450     retval = ((m_rawConst[7]) & (1 << ifiber)) != 0;
0451   }
0452   return retval;
0453 }
0454 
0455 bool HcalHTRData::unpack_per_channel_header(
0456     unsigned short header, int& flav, int& error_flags, int& capid0, int& channelid) {
0457   flav = (header >> 12) & 0x7;
0458   error_flags = (header >> 10) & 0x3;
0459   capid0 = (header >> 8) & 0x3;
0460   channelid = (header) & 0xFF;
0461   return (header & 0x8000) != 0;
0462 }
0463 
0464 bool HcalHTRData::unpackHistogram(int myfiber, int mysc, int capid, unsigned short* histogram) const {
0465   // check for histogram mode
0466   if (!isHistogramEvent())
0467     return false;
0468 
0469   int fiber1, fiber2;
0470   getHistogramFibers(fiber1, fiber2);
0471   if (fiber1 != myfiber && fiber2 != myfiber)
0472     return false;
0473 
0474   if (m_formatVersion == -1) {
0475     int offset = 6 + mysc * 4 * 32 + capid * 32;
0476     if (myfiber == fiber2)
0477       offset += 3 * 4 * 32;  // skip to the second half...
0478     for (int i = 0; i < 32; i++)
0479       histogram[i] = m_rawConst[offset + i];
0480     return true;
0481   } else {
0482     int offset = 8 + mysc * 4 * 32 + capid * 32;
0483     if (myfiber == fiber2)
0484       offset += 3 * 4 * 32;  // skip to the second half...
0485     for (int i = 0; i < 32; i++)
0486       histogram[i] = m_rawConst[offset + i];
0487     return true;
0488   }
0489 }