Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:11:04

0001 #include "EventFilter/SiStripRawToDigi/interface/SiStripFEDBufferGenerator.h"
0002 #include "FWCore/Utilities/interface/Exception.h"
0003 #include <cstring>
0004 #include <stdexcept>
0005 #include <cmath>
0006 
0007 namespace sistrip {
0008 
0009   //FEDStripData
0010 
0011   FEDStripData::FEDStripData(bool dataIsAlreadyConvertedTo8Bit, const size_t samplesPerChannel)
0012       : data_(FEDCH_PER_FED, ChannelData(dataIsAlreadyConvertedTo8Bit, samplesPerChannel)) {
0013     if (samplesPerChannel > SCOPE_MODE_MAX_SCOPE_LENGTH) {
0014       std::ostringstream ss;
0015       ss << "Scope length " << samplesPerChannel << " is too long. "
0016          << "Max scope length is " << SCOPE_MODE_MAX_SCOPE_LENGTH << ".";
0017       throw cms::Exception("FEDBufferGenerator") << ss.str();
0018     }
0019   }
0020 
0021   const FEDStripData::ChannelData& FEDStripData::channel(const uint8_t internalFEDChannelNum) const {
0022     try {
0023       return data_.at(internalFEDChannelNum);
0024     } catch (const std::out_of_range&) {
0025       std::ostringstream ss;
0026       ss << "Channel index out of range. (" << uint16_t(internalFEDChannelNum) << ") "
0027          << "Index should be in internal numbering scheme (0-95). ";
0028       throw cms::Exception("FEDBufferGenerator") << ss.str();
0029     }
0030   }
0031 
0032   void FEDStripData::ChannelData::setSample(const uint16_t sampleNumber, const uint16_t value) {
0033     if (value > 0x3FF) {
0034       std::ostringstream ss;
0035       ss << "Sample value (" << value << ") is too large. Maximum allowed is 1023. ";
0036       throw cms::Exception("FEDBufferGenerator") << ss.str();
0037     }
0038     try {
0039       data_.at(sampleNumber) = value;
0040     } catch (const std::out_of_range&) {
0041       std::ostringstream ss;
0042       ss << "Sample index out of range. "
0043          << "Requesting sample " << sampleNumber << " when channel has only " << data_.size() << " samples.";
0044       throw cms::Exception("FEDBufferGenerator") << ss.str();
0045     }
0046   }
0047 
0048   //FEDBufferPayload
0049 
0050   FEDBufferPayload::FEDBufferPayload(const std::vector<std::vector<uint8_t> >& channelBuffers) {
0051     //calculate size of buffer and allocate enough memory
0052     uint32_t totalSize = 0;
0053     for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0054       for (uint8_t iCh = 0; iCh < FEDCH_PER_FEUNIT; iCh++) {
0055         totalSize += channelBuffers[iFE * FEDCH_PER_FEUNIT + iCh].size();
0056       }
0057       //if it does not finish on a 64Bit word boundary then take into account padding
0058       if (totalSize % 8) {
0059         totalSize = ((totalSize / 8) + 1) * 8;
0060       }
0061     }
0062     data_.resize(totalSize);
0063     size_t indexInBuffer = 0;
0064     feLengths_.reserve(FEUNITS_PER_FED);
0065     //copy channel data into buffer with padding and update lengths
0066     for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0067       const size_t lengthAtStartOfFEUnit = indexInBuffer;
0068       //insert data for FE unit
0069       for (uint8_t iCh = 0; iCh < FEDCH_PER_FEUNIT; iCh++) {
0070         appendToBuffer(&indexInBuffer,
0071                        channelBuffers[iFE * FEDCH_PER_FEUNIT + iCh].begin(),
0072                        channelBuffers[iFE * FEDCH_PER_FEUNIT + iCh].end());
0073       }
0074       //store length
0075       feLengths_.push_back(indexInBuffer - lengthAtStartOfFEUnit);
0076       //add padding
0077       while (indexInBuffer % 8)
0078         appendToBuffer(&indexInBuffer, 0);
0079     }
0080   }
0081 
0082   const uint8_t* FEDBufferPayload::data() const {
0083     //vectors are guarenteed to be contiguous
0084     if (lengthInBytes())
0085       return &data_[0];
0086     //return NULL if there is no data yet
0087     else
0088       return nullptr;
0089   }
0090 
0091   uint16_t FEDBufferPayload::getFELength(const uint8_t internalFEUnitNum) const {
0092     try {
0093       return feLengths_.at(internalFEUnitNum);
0094     } catch (const std::out_of_range&) {
0095       std::ostringstream ss;
0096       ss << "Invalid FE unit number " << internalFEUnitNum << ". "
0097          << "Number should be in internal numbering scheme (0-7). ";
0098       throw cms::Exception("FEDBufferGenerator") << ss.str();
0099     }
0100   }
0101 
0102   FEDBufferPayload FEDBufferPayloadCreator::createPayload(FEDReadoutMode mode,
0103                                                           uint8_t packetCode,
0104                                                           const FEDStripData& data) const {
0105     std::vector<std::vector<uint8_t> > channelBuffers(FEDCH_PER_FED, std::vector<uint8_t>());
0106     for (size_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
0107       if (!feUnitsEnabled_[iCh / FEDCH_PER_FEUNIT])
0108         continue;
0109       fillChannelBuffer(&channelBuffers[iCh], mode, packetCode, data.channel(iCh), channelsEnabled_[iCh]);
0110     }
0111     return FEDBufferPayload(channelBuffers);
0112   }
0113 
0114   void FEDBufferPayloadCreator::fillChannelBuffer(std::vector<uint8_t>* channelBuffer,
0115                                                   FEDReadoutMode mode,
0116                                                   uint8_t packetCode,
0117                                                   const FEDStripData::ChannelData& data,
0118                                                   const bool channelEnabled) const {
0119     switch (mode) {
0120       case READOUT_MODE_SCOPE:
0121         fillRawChannelBuffer(channelBuffer, PACKET_CODE_SCOPE, data, channelEnabled, false);
0122         break;
0123       case READOUT_MODE_VIRGIN_RAW:
0124         switch (packetCode) {
0125           case PACKET_CODE_VIRGIN_RAW:
0126             fillRawChannelBuffer(channelBuffer, PACKET_CODE_VIRGIN_RAW, data, channelEnabled, true);
0127             break;
0128           case PACKET_CODE_VIRGIN_RAW10:
0129             fillRawChannelBuffer(channelBuffer, PACKET_CODE_VIRGIN_RAW10, data, channelEnabled, true);
0130             break;
0131           case PACKET_CODE_VIRGIN_RAW8_BOTBOT:
0132             fillRawChannelBuffer(channelBuffer, PACKET_CODE_VIRGIN_RAW8_BOTBOT, data, channelEnabled, true);
0133             break;
0134           case PACKET_CODE_VIRGIN_RAW8_TOPBOT:
0135             fillRawChannelBuffer(channelBuffer, PACKET_CODE_VIRGIN_RAW8_TOPBOT, data, channelEnabled, true);
0136             break;
0137         }
0138         break;
0139       case READOUT_MODE_PROC_RAW:
0140         fillRawChannelBuffer(channelBuffer, PACKET_CODE_PROC_RAW, data, channelEnabled, false);
0141         break;
0142       case READOUT_MODE_ZERO_SUPPRESSED:
0143         //case READOUT_MODE_ZERO_SUPPRESSED_CMOVERRIDE:
0144         fillZeroSuppressedChannelBuffer(channelBuffer, packetCode, data, channelEnabled);
0145         break;
0146       case READOUT_MODE_ZERO_SUPPRESSED_LITE10:
0147       case READOUT_MODE_ZERO_SUPPRESSED_LITE10_CMOVERRIDE:
0148       case READOUT_MODE_ZERO_SUPPRESSED_LITE8:
0149       case READOUT_MODE_ZERO_SUPPRESSED_LITE8_CMOVERRIDE:
0150       case READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT:
0151       case READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT_CMOVERRIDE:
0152       case READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT:
0153       case READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT_CMOVERRIDE:
0154         fillZeroSuppressedLiteChannelBuffer(channelBuffer, data, channelEnabled, mode);
0155         break;
0156       case READOUT_MODE_PREMIX_RAW:
0157         fillPreMixRawChannelBuffer(channelBuffer, data, channelEnabled);
0158         break;
0159       default:
0160         std::ostringstream ss;
0161         ss << "Invalid readout mode " << mode;
0162         throw cms::Exception("FEDBufferGenerator") << ss.str();
0163         break;
0164     }
0165   }
0166 
0167   void FEDBufferPayloadCreator::fillRawChannelBuffer(std::vector<uint8_t>* channelBuffer,
0168                                                      const uint8_t packetCode,
0169                                                      const FEDStripData::ChannelData& data,
0170                                                      const bool channelEnabled,
0171                                                      const bool reorderData) const {
0172     const uint16_t nSamples = data.size();
0173     uint16_t channelLength = 0;
0174     switch (packetCode) {
0175       case PACKET_CODE_VIRGIN_RAW:
0176         channelLength = nSamples * 2 + 3;
0177         break;
0178       case PACKET_CODE_VIRGIN_RAW10:
0179         channelLength = std::ceil(nSamples * 1.25) + 3;
0180         break;
0181       case PACKET_CODE_VIRGIN_RAW8_BOTBOT:
0182       case PACKET_CODE_VIRGIN_RAW8_TOPBOT:
0183         channelLength = nSamples * 1 + 3;
0184         break;
0185     }
0186     channelBuffer->reserve(channelLength);
0187     //length (max length is 0xFFF)
0188     channelBuffer->push_back(channelLength & 0xFF);
0189     channelBuffer->push_back((channelLength & 0xF00) >> 8);
0190     //packet code
0191     channelBuffer->push_back(packetCode);
0192     //channel samples
0193     uint16_t sampleValue_pre = 0;
0194     for (uint16_t sampleNumber = 0; sampleNumber < nSamples; sampleNumber++) {
0195       const uint16_t sampleIndex =
0196           (reorderData ? FEDStripOrdering::physicalOrderForStripInChannel(sampleNumber) : sampleNumber);
0197       const uint16_t sampleValue = (channelEnabled ? data.getSample(sampleIndex) : 0);
0198       switch (packetCode) {
0199         case PACKET_CODE_VIRGIN_RAW:
0200           channelBuffer->push_back(sampleValue & 0xFF);
0201           channelBuffer->push_back((sampleValue & 0x300) >> 8);
0202           break;
0203         case PACKET_CODE_VIRGIN_RAW10:
0204           if (sampleNumber % 4 == 0) {
0205             channelBuffer->push_back((sampleValue & 0x3FC) >> 2);
0206           } else if (sampleNumber % 4 == 1) {
0207             channelBuffer->push_back(((sampleValue_pre & 0x3) << 6) | ((sampleValue & 0x3F0) >> 4));
0208           } else if (sampleNumber % 4 == 2) {
0209             channelBuffer->push_back(((sampleValue_pre & 0xF) << 4) | ((sampleValue & 0x3C0) >> 6));
0210           } else if (sampleNumber % 4 == 3) {
0211             channelBuffer->push_back(((sampleValue_pre & 0x3F) << 2) | ((sampleValue & 0x300) >> 8));
0212             channelBuffer->push_back(sampleValue & 0xFF);
0213           }
0214           sampleValue_pre = sampleValue;
0215           break;
0216         case PACKET_CODE_VIRGIN_RAW8_BOTBOT:
0217           channelBuffer->push_back((sampleValue & 0x3FC) >> 2);
0218           break;
0219         case PACKET_CODE_VIRGIN_RAW8_TOPBOT:
0220           channelBuffer->push_back((sampleValue & 0x1FE) >> 1);
0221           break;
0222       }
0223     }
0224   }
0225 
0226   void FEDBufferPayloadCreator::fillZeroSuppressedChannelBuffer(std::vector<uint8_t>* channelBuffer,
0227                                                                 const uint8_t packetCode,
0228                                                                 const FEDStripData::ChannelData& data,
0229                                                                 const bool channelEnabled) const {
0230     channelBuffer->reserve(50);
0231     //if channel is disabled then create empty channel header and return
0232     if (!channelEnabled) {
0233       //min length 7
0234       channelBuffer->push_back(7);
0235       channelBuffer->push_back(0);
0236       //packet code
0237       channelBuffer->push_back(packetCode);
0238       //4 bytes of medians
0239       channelBuffer->insert(channelBuffer->end(), 4, 0);
0240       return;
0241     }
0242     //if channel is not empty
0243     //add space for channel length
0244     channelBuffer->push_back(0xFF);
0245     channelBuffer->push_back(0xFF);
0246     //packet code
0247     channelBuffer->push_back(packetCode);
0248     //add medians
0249     const std::pair<uint16_t, uint16_t> medians = data.getMedians();
0250     channelBuffer->push_back(medians.first & 0xFF);
0251     channelBuffer->push_back((medians.first & 0x300) >> 8);
0252     channelBuffer->push_back(medians.second & 0xFF);
0253     channelBuffer->push_back((medians.second & 0x300) >> 8);
0254     //clusters
0255     fillClusterData(channelBuffer, packetCode, data, READOUT_MODE_ZERO_SUPPRESSED);
0256     //set length
0257     const uint16_t length = channelBuffer->size();
0258     (*channelBuffer)[0] = (length & 0xFF);
0259     (*channelBuffer)[1] = ((length & 0x300) >> 8);
0260   }
0261 
0262   void FEDBufferPayloadCreator::fillZeroSuppressedLiteChannelBuffer(std::vector<uint8_t>* channelBuffer,
0263                                                                     const FEDStripData::ChannelData& data,
0264                                                                     const bool channelEnabled,
0265                                                                     const FEDReadoutMode mode) const {
0266     channelBuffer->reserve(50);
0267     //if channel is disabled then create empty channel header and return
0268     if (!channelEnabled) {
0269       //min length 2
0270       channelBuffer->push_back(2);
0271       channelBuffer->push_back(0);
0272       return;
0273     }
0274     //if channel is not empty
0275     //add space for channel length
0276     channelBuffer->push_back(0xFF);
0277     channelBuffer->push_back(0xFF);
0278     //clusters
0279     fillClusterData(channelBuffer, 0, data, mode);
0280     //set fibre length
0281     const uint16_t length = channelBuffer->size();
0282     (*channelBuffer)[0] = (length & 0xFF);
0283     (*channelBuffer)[1] = ((length & 0x300) >> 8);
0284   }
0285 
0286   void FEDBufferPayloadCreator::fillPreMixRawChannelBuffer(std::vector<uint8_t>* channelBuffer,
0287                                                            const FEDStripData::ChannelData& data,
0288                                                            const bool channelEnabled) const {
0289     channelBuffer->reserve(50);
0290     //if channel is disabled then create empty channel header and return
0291     if (!channelEnabled) {
0292       //min length 7
0293       channelBuffer->push_back(7);
0294       channelBuffer->push_back(0);
0295       //packet code
0296       channelBuffer->push_back(PACKET_CODE_ZERO_SUPPRESSED);
0297       //4 bytes of medians
0298       channelBuffer->insert(channelBuffer->end(), 4, 0);
0299       return;
0300     }
0301     //if channel is not empty
0302     //add space for channel length
0303     channelBuffer->push_back(0xFF);
0304     channelBuffer->push_back(0xFF);
0305     //packet code
0306     channelBuffer->push_back(PACKET_CODE_ZERO_SUPPRESSED);
0307     //add medians
0308     const std::pair<uint16_t, uint16_t> medians = data.getMedians();
0309     channelBuffer->push_back(medians.first & 0xFF);
0310     channelBuffer->push_back((medians.first & 0x300) >> 8);
0311     channelBuffer->push_back(medians.second & 0xFF);
0312     channelBuffer->push_back((medians.second & 0x300) >> 8);
0313     //clusters
0314     fillClusterDataPreMixMode(channelBuffer, data);
0315     //set length
0316     const uint16_t length = channelBuffer->size();
0317     (*channelBuffer)[0] = (length & 0xFF);
0318     (*channelBuffer)[1] = ((length & 0x300) >> 8);
0319   }
0320 
0321   void FEDBufferPayloadCreator::fillClusterData(std::vector<uint8_t>* channelBuffer,
0322                                                 uint8_t packetCode,
0323                                                 const FEDStripData::ChannelData& data,
0324                                                 const FEDReadoutMode mode) const {
0325     // ZS lite: retrieve "packet code"
0326     switch (mode) {
0327       case READOUT_MODE_ZERO_SUPPRESSED_LITE8:
0328         packetCode = PACKET_CODE_ZERO_SUPPRESSED;
0329         break;
0330       case READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT:
0331       case READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT_CMOVERRIDE:
0332         packetCode = PACKET_CODE_ZERO_SUPPRESSED8_TOPBOT;
0333         break;
0334       case READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT:
0335       case READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT_CMOVERRIDE:
0336         packetCode = PACKET_CODE_ZERO_SUPPRESSED8_BOTBOT;
0337         break;
0338       case READOUT_MODE_ZERO_SUPPRESSED_LITE10:
0339       case READOUT_MODE_ZERO_SUPPRESSED_LITE10_CMOVERRIDE:
0340         packetCode = PACKET_CODE_ZERO_SUPPRESSED10;
0341         break;
0342       default:;
0343     }
0344     const bool is10Bit = (packetCode == PACKET_CODE_ZERO_SUPPRESSED10);
0345     const uint16_t bShift = (packetCode == PACKET_CODE_ZERO_SUPPRESSED8_BOTBOT
0346                                  ? 2
0347                                  : (packetCode == PACKET_CODE_ZERO_SUPPRESSED8_TOPBOT ? 1 : 0));
0348 
0349     uint16_t clusterSize = 0;  // counter
0350     std::size_t size_pos = 0;  // index of cluster size
0351     uint16_t adc_pre = 0;
0352     const uint16_t nSamples = data.size();
0353     for (uint16_t strip = 0; strip < nSamples; ++strip) {
0354       const uint16_t adc = is10Bit ? data.get10BitSample(strip) : data.get8BitSample(strip, bShift);
0355       if (adc) {
0356         if (clusterSize == 0 || strip == STRIPS_PER_APV) {
0357           if (clusterSize) {
0358             if (is10Bit && (clusterSize % 4)) {
0359               channelBuffer->push_back(adc_pre);
0360             }
0361             (*channelBuffer)[size_pos] = clusterSize;
0362             clusterSize = 0;
0363           }
0364           // cluster header: first strip and size
0365           channelBuffer->push_back(strip);
0366           size_pos = channelBuffer->size();
0367           channelBuffer->push_back(0);  // for clustersize
0368         }
0369         if (!is10Bit) {
0370           channelBuffer->push_back(adc & 0xFF);
0371         } else {
0372           if (clusterSize % 4 == 0) {
0373             channelBuffer->push_back((adc & 0x3FC) >> 2);
0374             adc_pre = ((adc & 0x3) << 6);
0375           } else if (clusterSize % 4 == 1) {
0376             channelBuffer->push_back(adc_pre | ((adc & 0x3F0) >> 4));
0377             adc_pre = ((adc & 0xF) << 4);
0378           } else if (clusterSize % 4 == 2) {
0379             channelBuffer->push_back(adc_pre | ((adc & 0x3C0) >> 6));
0380             adc_pre = ((adc & 0x3F) << 2);
0381           } else if (clusterSize % 4 == 3) {
0382             channelBuffer->push_back(adc_pre | ((adc & 0x300) >> 8));
0383             channelBuffer->push_back(adc & 0xFF);
0384             adc_pre = 0;
0385           }
0386         }
0387         ++clusterSize;
0388       } else if (clusterSize) {
0389         if (is10Bit && (clusterSize % 4)) {
0390           channelBuffer->push_back(adc_pre);
0391         }
0392         (*channelBuffer)[size_pos] = clusterSize;
0393         clusterSize = 0;
0394       }
0395     }
0396     if (clusterSize) {
0397       (*channelBuffer)[size_pos] = clusterSize;
0398       if (is10Bit && (clusterSize % 4)) {
0399         channelBuffer->push_back(adc_pre);
0400       }
0401     }
0402   }
0403 
0404   void FEDBufferPayloadCreator::fillClusterDataPreMixMode(std::vector<uint8_t>* channelBuffer,
0405                                                           const FEDStripData::ChannelData& data) const {
0406     uint16_t clusterSize = 0;
0407     const uint16_t nSamples = data.size();
0408     for (uint16_t strip = 0; strip < nSamples; ++strip) {
0409       const uint16_t adc = data.get10BitSample(strip);
0410 
0411       if (adc) {
0412         if (clusterSize == 0 || strip == STRIPS_PER_APV) {
0413           if (clusterSize) {
0414             *(channelBuffer->end() - 2 * clusterSize - 1) = clusterSize;
0415             clusterSize = 0;
0416           }
0417           channelBuffer->push_back(strip);
0418           channelBuffer->push_back(0);  //clustersize
0419         }
0420         channelBuffer->push_back(adc & 0xFF);
0421         channelBuffer->push_back((adc & 0x0300) >> 8);
0422 
0423         ++clusterSize;
0424       }
0425 
0426       else if (clusterSize) {
0427         *(channelBuffer->end() - 2 * clusterSize - 1) = clusterSize;
0428         clusterSize = 0;
0429       }
0430     }
0431     if (clusterSize) {
0432       *(channelBuffer->end() - 2 * clusterSize - 1) = clusterSize;
0433     }
0434   }
0435 
0436   //FEDBufferGenerator
0437 
0438   FEDBufferGenerator::FEDBufferGenerator(const uint32_t l1ID,
0439                                          const uint16_t bxID,
0440                                          const std::vector<bool>& feUnitsEnabled,
0441                                          const std::vector<bool>& channelsEnabled,
0442                                          const FEDReadoutMode readoutMode,
0443                                          const FEDHeaderType headerType,
0444                                          const FEDBufferFormat bufferFormat,
0445                                          const FEDDAQEventType evtType)
0446       : defaultDAQHeader_(l1ID, bxID, 0, evtType),
0447         defaultDAQTrailer_(0, 0),
0448         defaultTrackerSpecialHeader_(bufferFormat, readoutMode, headerType),
0449         defaultFEHeader_(FEDFEHeader::newFEHeader(headerType)),
0450         feUnitsEnabled_(feUnitsEnabled),
0451         channelsEnabled_(channelsEnabled) {
0452     if (!defaultFEHeader_.get()) {
0453       std::ostringstream ss;
0454       ss << "Bad header format: " << headerType;
0455       throw cms::Exception("FEDBufferGenerator") << ss.str();
0456     }
0457   }
0458 
0459   bool FEDBufferGenerator::getFEUnitEnabled(const uint8_t internalFEUnitNumber) const {
0460     try {
0461       return feUnitsEnabled_.at(internalFEUnitNumber);
0462     } catch (const std::out_of_range&) {
0463       std::ostringstream ss;
0464       ss << "Invalid FE unit number " << internalFEUnitNumber << ". Should be in internal numbering scheme (0-7)";
0465       throw cms::Exception("FEDBufferGenerator") << ss.str();
0466     }
0467   }
0468 
0469   bool FEDBufferGenerator::getChannelEnabled(const uint8_t internalFEDChannelNumber) const {
0470     try {
0471       return channelsEnabled_.at(internalFEDChannelNumber);
0472     } catch (const std::out_of_range&) {
0473       std::ostringstream ss;
0474       ss << "Invalid channel number " << internalFEDChannelNumber << ". "
0475          << "Should be in internal numbering scheme (0-95)";
0476       throw cms::Exception("FEDBufferGenerator") << ss.str();
0477     }
0478   }
0479 
0480   FEDBufferGenerator& FEDBufferGenerator::setFEUnitEnable(const uint8_t internalFEUnitNumber, const bool enabled) {
0481     try {
0482       feUnitsEnabled_.at(internalFEUnitNumber) = enabled;
0483     } catch (const std::out_of_range&) {
0484       std::ostringstream ss;
0485       ss << "Invalid FE unit number " << internalFEUnitNumber << ". "
0486          << "Should be in internal numbering scheme (0-7)";
0487       throw cms::Exception("FEDBufferGenerator") << ss.str();
0488     }
0489     return *this;
0490   }
0491 
0492   FEDBufferGenerator& FEDBufferGenerator::setChannelEnable(const uint8_t internalFEDChannelNumber, const bool enabled) {
0493     try {
0494       channelsEnabled_.at(internalFEDChannelNumber) = enabled;
0495     } catch (const std::out_of_range&) {
0496       std::ostringstream ss;
0497       ss << "Invalid channel number " << internalFEDChannelNumber << ". "
0498          << "Should be in internal numbering scheme (0-95)";
0499       throw cms::Exception("FEDBufferGenerator") << ss.str();
0500     }
0501     return *this;
0502   }
0503 
0504   FEDBufferGenerator& FEDBufferGenerator::setFEUnitEnables(const std::vector<bool>& feUnitEnables) {
0505     if (feUnitEnables.size() != FEUNITS_PER_FED) {
0506       std::ostringstream ss;
0507       ss << "Setting FE enable vector with vector which is the wrong size. Size is " << feUnitEnables.size()
0508          << " it must be " << FEUNITS_PER_FED << "." << std::endl;
0509       throw cms::Exception("FEDBufferGenerator") << ss.str();
0510     }
0511     feUnitsEnabled_ = feUnitEnables;
0512     return *this;
0513   }
0514 
0515   FEDBufferGenerator& FEDBufferGenerator::setChannelEnables(const std::vector<bool>& channelEnables) {
0516     if (channelEnables.size() != FEDCH_PER_FED) {
0517       std::ostringstream ss;
0518       ss << "Setting FED channel enable vector with vector which is the wrong size. Size is " << channelEnables.size()
0519          << " it must be " << FEDCH_PER_FED << "." << std::endl;
0520       throw cms::Exception("FEDBufferGenerator") << ss.str();
0521     }
0522     channelsEnabled_ = channelEnables;
0523     return *this;
0524   }
0525 
0526   void FEDBufferGenerator::generateBuffer(FEDRawData* rawDataObject,
0527                                           const FEDStripData& data,
0528                                           uint16_t sourceID,
0529                                           uint8_t packetCode) const {
0530     //deal with disabled FE units and channels properly (FE enables, status bits)
0531     TrackerSpecialHeader tkSpecialHeader(defaultTrackerSpecialHeader_);
0532     std::unique_ptr<FEDFEHeader> fedFeHeader(defaultFEHeader_->clone());
0533     for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0534       const bool enabled = feUnitsEnabled_[iFE];
0535       tkSpecialHeader.setFEEnableForFEUnit(iFE, enabled);
0536       if (!enabled) {
0537         for (uint8_t iFEUnitChannel = 0; iFEUnitChannel < FEDCH_PER_FEUNIT; iFEUnitChannel++) {
0538           fedFeHeader->setChannelStatus(iFE, iFEUnitChannel, FEDChannelStatus(0));
0539         }
0540       }
0541     }
0542     for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
0543       if (!channelsEnabled_[iCh]) {
0544         fedFeHeader->setChannelStatus(iCh, FEDChannelStatus(0));
0545       }
0546     }
0547     //set the source ID
0548     FEDDAQHeader daqHeader(defaultDAQHeader_);
0549     daqHeader.setSourceID(sourceID);
0550     //build payload
0551     const FEDBufferPayloadCreator payloadPacker(feUnitsEnabled_, channelsEnabled_);
0552     const FEDBufferPayload payload = payloadPacker(getReadoutMode(), packetCode, data);
0553     //fill FE lengths
0554     for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0555       fedFeHeader->setFEUnitLength(iFE, payload.getFELength(iFE));
0556     }
0557     //resize buffer
0558     rawDataObject->resize(bufferSizeInBytes(*fedFeHeader, payload));
0559     //fill buffer
0560     fillBuffer(rawDataObject->data(), daqHeader, defaultDAQTrailer_, tkSpecialHeader, *fedFeHeader, payload);
0561   }
0562 
0563   void FEDBufferGenerator::fillBuffer(uint8_t* pointerToStartOfBuffer,
0564                                       const FEDDAQHeader& daqHeader,
0565                                       const FEDDAQTrailer& daqTrailer,
0566                                       const TrackerSpecialHeader& tkSpecialHeader,
0567                                       const FEDFEHeader& feHeader,
0568                                       const FEDBufferPayload& payload) {
0569     //set the length in the DAQ trailer
0570     const size_t lengthInBytes = bufferSizeInBytes(feHeader, payload);
0571     FEDDAQTrailer updatedDAQTrailer(daqTrailer);
0572     updatedDAQTrailer.setEventLengthIn64BitWords(lengthInBytes / 8);
0573     //copy pieces into buffer in order
0574     uint8_t* bufferPointer = pointerToStartOfBuffer;
0575     memcpy(bufferPointer, daqHeader.data(), 8);
0576     bufferPointer += 8;
0577     memcpy(bufferPointer, tkSpecialHeader.data(), 8);
0578     bufferPointer += 8;
0579     memcpy(bufferPointer, feHeader.data(), feHeader.lengthInBytes());
0580     bufferPointer += feHeader.lengthInBytes();
0581     memcpy(bufferPointer, payload.data(), payload.lengthInBytes());
0582     bufferPointer += payload.lengthInBytes();
0583     memcpy(bufferPointer, updatedDAQTrailer.data(), 8);
0584     //update CRC
0585     const uint16_t crc = calculateFEDBufferCRC(pointerToStartOfBuffer, lengthInBytes);
0586     updatedDAQTrailer.setCRC(crc);
0587     memcpy(bufferPointer, updatedDAQTrailer.data(), 8);
0588     //word swap if necessary
0589     if (tkSpecialHeader.wasSwapped()) {
0590       for (size_t i = 0; i < 8; i++) {
0591         bufferPointer[i] = bufferPointer[i ^ 4];
0592       }
0593     }
0594   }
0595 
0596 }  // namespace sistrip