Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #include "EventFilter/CSCRawToDigi/interface/CSCALCTHeader.h"
0002 #include "EventFilter/CSCRawToDigi/interface/CSCDMBHeader.h"
0003 #include "DataFormats/MuonDetId/interface/CSCDetId.h"
0004 #include "EventFilter/CSCRawToDigi/interface/bitset_append.h"
0005 #include "EventFilter/CSCRawToDigi/interface/cscPackerCompare.h"
0006 #include <iomanip>
0007 
0008 #ifdef LOCAL_UNPACK
0009 
0010 bool CSCALCTHeader::debug = false;
0011 short unsigned int CSCALCTHeader::firmwareVersion = 2007;
0012 
0013 #else
0014 
0015 #include <atomic>
0016 
0017 std::atomic<bool> CSCALCTHeader::debug{false};
0018 std::atomic<short unsigned int> CSCALCTHeader::firmwareVersion{2007};
0019 
0020 #endif
0021 
0022 CSCALCTHeader::CSCALCTHeader(int chamberType)
0023     : header2006(chamberType), header2007(chamberType) {  //constructor for digi->raw packing based on header2006
0024   if (firmwareVersion == 2006) {
0025     memcpy(theOriginalBuffer, &header2006, header2006.sizeInWords() * 2);
0026   } else if (firmwareVersion == 2007) {
0027     memcpy(theOriginalBuffer, &header2007, header2007.sizeInWords() * 2);
0028     // assume no virtex or masks or registers
0029     sizeInWords2007_ = header2007.sizeInWords() + header2007.lctBins * CSCALCT::sizeInWords() * 2;
0030     theALCTs.resize(header2007.lctBins * 2);
0031   } else {
0032     edm::LogError("CSCALCTHeader|CSCRawToDigi")
0033         << "Cannot construct ALCT header: ALCT firmware version is bad/not defined!" << firmwareVersion;
0034   }
0035 }
0036 
0037 CSCALCTHeader::CSCALCTHeader(const unsigned short *buf) {
0038   ///collision and hot channel masks are variable sized
0039   ///the sizes vary depending on type of the ALCT board
0040   ///                                        number of words for various
0041   ///                                        alct board types:  1  2  3     5  6
0042   constexpr unsigned short int collisionMaskWordcount[7] = {8, 8, 12, 16, 16, 24, 28};
0043   constexpr unsigned short int hotChannelMaskWordcount[7] = {18, 18, 24, 36, 36, 48, 60};
0044 
0045   ///first determine the correct format
0046   if (buf[0] == 0xDB0A) {
0047     firmwareVersion = 2007;
0048   } else if ((buf[0] & 0xF800) == 0x6000) {
0049     firmwareVersion = 2006;
0050   } else {
0051     edm::LogError("CSCALCTHeader|CSCRawToDigi") << "failed to determine ALCT firmware version!!";
0052   }
0053 
0054   LogTrace("CSCALCTHeader|CSCRawToDigi") << "firmware version - " << firmwareVersion;
0055 
0056   ///Now fill data
0057 #ifdef LOCAL_UNPACK
0058   switch (firmwareVersion) {
0059 #else
0060   switch (firmwareVersion.load()) {
0061 #endif
0062     case 2006:
0063       header2006.setFromBuffer(buf);  ///the header part
0064       buf += header2006.sizeInWords();
0065       alcts2006.setFromBuffer(buf);  ///the alct0 and alct1
0066       buf += alcts2006.sizeInWords();
0067       break;
0068 
0069     case 2007:
0070       header2007.setFromBuffer(buf);  ///the fixed sized header part
0071       buf += header2007.sizeInWords();
0072       sizeInWords2007_ = header2007.sizeInWords();
0073       ///now come the variable parts
0074       if (header2007.configPresent == 1) {
0075         virtexID.setFromBuffer(buf);
0076         buf += virtexID.sizeInWords();
0077         sizeInWords2007_ = virtexID.sizeInWords();
0078         configRegister.setFromBuffer(buf);
0079         buf += configRegister.sizeInWords();
0080         sizeInWords2007_ += configRegister.sizeInWords();
0081 
0082         collisionMasks.resize(collisionMaskWordcount[header2007.boardType]);
0083         for (unsigned int i = 0; i < collisionMaskWordcount[header2007.boardType]; ++i) {
0084           collisionMasks[i].setFromBuffer(buf);
0085           buf += collisionMasks[i].sizeInWords();
0086           sizeInWords2007_ += collisionMasks[i].sizeInWords();
0087         }
0088 
0089         hotChannelMasks.resize(hotChannelMaskWordcount[header2007.boardType]);
0090         for (unsigned int i = 0; i < hotChannelMaskWordcount[header2007.boardType]; ++i) {
0091           hotChannelMasks[i].setFromBuffer(buf);
0092           buf += hotChannelMasks[i].sizeInWords();
0093           sizeInWords2007_ += hotChannelMasks[i].sizeInWords();
0094         }
0095       }
0096 
0097       theALCTs.resize(header2007.lctBins * 2);  ///2007 has LCTbins * 2 alct words
0098       for (int i = 0; i < header2007.lctBins * 2; ++i) {
0099         theALCTs[i].setFromBuffer(buf);
0100         buf += theALCTs[i].sizeInWords();
0101         sizeInWords2007_ += theALCTs[i].sizeInWords();
0102       }
0103 
0104       ALCTDigis();
0105       break;
0106 
0107     default:
0108       edm::LogError("CSCALCTHeader|CSCRawToDigi") << "couldn't construct: ALCT firmware version is bad/not defined!";
0109       break;
0110   }
0111 
0112   ///also store raw data buffer too; it is later returned by data() method
0113   if ((firmwareVersion == 2006) || (firmwareVersion == 2007))
0114     memcpy(theOriginalBuffer, buf - sizeInWords(), sizeInWords() * 2);
0115 }
0116 
0117 CSCALCTHeader::CSCALCTHeader(const CSCALCTStatusDigi &digi) { CSCALCTHeader(digi.header()); }
0118 
0119 void CSCALCTHeader::setEventInformation(const CSCDMBHeader &dmb) {
0120 #ifdef LOCAL_UNPACK
0121   switch (firmwareVersion) {
0122 #else
0123   switch (firmwareVersion.load()) {
0124 #endif
0125     case 2006: {
0126       header2006.setEventInformation(dmb);
0127       break;
0128     }
0129     case 2007: {
0130       header2007.setEventInformation(dmb);
0131       break;
0132     }
0133     default:
0134       edm::LogError("CSCALCTHeader|CSCRawToDigi")
0135           << "setEventInformation: ALCT firmware version is bad/not defined!" << firmwareVersion;
0136       break;
0137   }
0138 }
0139 
0140 unsigned short CSCALCTHeader::nLCTChipRead() const {  ///header2006 method
0141   if (firmwareVersion == 2006) {
0142     return header2006.nLCTChipRead();
0143   } else {
0144     // nLCTChip obsolete in ALCT2007 format (email Andrey K. & Victor B., 20.10.2008)
0145     // and we don't think anyone makes uses of this call.
0146     //    edm::LogError("CSCALCTHeader|CSCRawToDigi")
0147     //      <<"How is nLCTChipRead() supposed to work for ALCTHeader2007?";
0148   }
0149   return 0;
0150 }
0151 
0152 std::vector<CSCALCTDigi> CSCALCTHeader::ALCTDigis() const {
0153   std::vector<CSCALCTDigi> result;
0154 
0155 #ifdef LOCAL_UNPACK
0156   switch (firmwareVersion) {
0157 #else
0158   switch (firmwareVersion.load()) {
0159 #endif
0160     case 2006: {
0161       result = alcts2006.ALCTDigis();
0162       break;
0163     }
0164     case 2007: {
0165       result.reserve(theALCTs.size());
0166       for (unsigned int i = 0; i < theALCTs.size(); ++i) {  ///loop over all alct words
0167         CSCALCTDigi digi(theALCTs[i].valid,
0168                          theALCTs[i].quality,
0169                          theALCTs[i].accel,
0170                          theALCTs[i].pattern,
0171                          theALCTs[i].keyWire,
0172                          (int)i / 2,
0173                          i % 2 + 1);
0174         result.push_back(digi);
0175       }
0176       break;
0177     }
0178     default:
0179       edm::LogError("CSCALCTHeader|CSCRawToDigi")
0180           << "Empty Digis: ALCT firmware version is bad/not defined!" << firmwareVersion;
0181       break;
0182   }
0183   for (unsigned i = 0; i < result.size(); ++i) {
0184     result[i].setFullBX(BXNCount());
0185   }
0186   return result;
0187 }
0188 
0189 void CSCALCTHeader::add(const std::vector<CSCALCTDigi> &digis) {
0190   if (firmwareVersion == 2006) {
0191     alcts2006.add(digis);
0192   } else if (firmwareVersion == 2007) {
0193     if (theALCTs.empty()) {
0194       theALCTs.resize(header2007.lctBins * 2);
0195     }
0196     for (std::vector<CSCALCTDigi>::const_iterator digi = digis.begin(); digi != digis.end(); ++digi) {
0197       int bx = digi->getBX();
0198       if (bx < (int)header2007.lctBins) {
0199         // 2 ALCTs per bx
0200         int i = bx * 2;
0201         int q1 = theALCTs[i].quality;
0202         int q2 = theALCTs[i + 1].quality;
0203         // see if it's non=blank
0204         if (!theALCTs[i].valid) {
0205           theALCTs[i] = CSCALCT(*digi);
0206         }
0207         // new best LCT
0208         else if (digi->getQuality() > q1) {
0209           theALCTs[i + 1] = theALCTs[i];
0210           theALCTs[i] = CSCALCT(*digi);
0211         }
0212         // new second best
0213         else if (!theALCTs[i + 1].valid || (digi->getQuality() > q2)) {
0214           theALCTs[i + 1] = CSCALCT(*digi);
0215         }
0216       }
0217     }
0218   }
0219 }
0220 
0221 /// Add ALCT anodes HMT shower bits per ALCT BX
0222 void CSCALCTHeader::addShower(const std::vector<CSCShowerDigi> &digis) {
0223   if (firmwareVersion == 2007) {
0224     if (theALCTs.empty()) {
0225       theALCTs.resize(header2007.lctBins * 2);
0226     }
0227     for (std::vector<CSCShowerDigi>::const_iterator digi = digis.begin(); digi != digis.end(); ++digi) {
0228       int bx = digi - digis.begin();
0229       if (bx < (int)header2007.lctBins) {
0230         const CSCShowerDigi &digi = digis[bx];
0231         int i = bx * 2;
0232         unsigned hmt_bits = digi.isValid() ? digi.bitsInTime() : 0;
0233         theALCTs[i].reserved = hmt_bits & 0x3;
0234         theALCTs[i + 1].reserved = hmt_bits & 0x3;
0235       }
0236     }
0237   }
0238 }
0239 
0240 boost::dynamic_bitset<> CSCALCTHeader::pack() {
0241   boost::dynamic_bitset<> result;
0242   if (firmwareVersion == 2006) {
0243     boost::dynamic_bitset<> header =
0244         bitset_utilities::ushortToBitset(header2006.sizeInWords() * 16, (unsigned short *)&header2006);
0245     boost::dynamic_bitset<> alcts =
0246         bitset_utilities::ushortToBitset(alcts2006.sizeInWords() * 16, (unsigned short *)&alcts2006);
0247     result = bitset_utilities::append(header, alcts);
0248 
0249     bitset_utilities::bitsetToChar(result, (unsigned char *)data());
0250   }
0251 
0252   else if (firmwareVersion == 2007) {
0253     result = bitset_utilities::ushortToBitset(header2007.sizeInWords() * 16, (unsigned short *)&header2007);
0254 
0255     for (unsigned i = 0; i < theALCTs.size(); ++i) {
0256       boost::dynamic_bitset<> alct =
0257           bitset_utilities::ushortToBitset(theALCTs[i].sizeInWords() * 16, (unsigned short *)&theALCTs[i]);
0258       result = bitset_utilities::append(result, alct);
0259     }
0260 
0261     bitset_utilities::bitsetToChar(result, (unsigned char *)data());
0262   }
0263   return result;
0264 }
0265 
0266 void CSCALCTHeader::selfTest(int firmware) {
0267   firmwareVersion = firmware;
0268   CSCALCTDigi alct0(true, 1, 1, 1, 10, 6, 1);
0269   CSCALCTDigi alct1(true, 1, 1, 0, 11, 6, 2);
0270 
0271   // tests packing and unpacking
0272   for (int station = 1; station <= 4; ++station) {
0273     CSCDetId detId(1, station, 1, 1, 0);
0274 
0275     std::vector<CSCALCTDigi> oldAlcts;
0276     oldAlcts.push_back(alct0);
0277     oldAlcts.push_back(alct1);
0278     CSCALCTHeader alctHeader(detId.iChamberType());
0279 
0280     alctHeader.add(oldAlcts);
0281 
0282     std::vector<CSCALCTDigi> alcts = alctHeader.ALCTDigis();
0283     // pick out the valid ones
0284     std::vector<CSCALCTDigi> validALCTs;
0285     for (std::vector<CSCALCTDigi>::const_iterator alctItr = alcts.begin(); alctItr != alcts.end(); ++alctItr) {
0286       if (alctItr->isValid()) {
0287         validALCTs.push_back(*alctItr);
0288       }
0289     }
0290     assert(validALCTs[0] == alct0);
0291     assert(validALCTs[1] == alct1);
0292     //cscClassPackerCompare(alctHeader);
0293   }
0294 }
0295 
0296 std::ostream &operator<<(std::ostream &os, const CSCALCTHeader &header) {
0297   os << "ALCT HEADER CSCID " << header.CSCID() << "  L1ACC " << header.L1Acc() << std::endl;
0298   os << " time samples " << header.NTBins() << std::endl;
0299   return os;
0300 }