Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #include "EventFilter/RPCRawToDigi/plugins/RPCTwinMuxRawToDigi.h"
0002 
0003 #include <memory>
0004 
0005 #include "DataFormats/Common/interface/Handle.h"
0006 #include "FWCore/Framework/interface/Event.h"
0007 #include "FWCore/Framework/interface/EventSetup.h"
0008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0009 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0010 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0011 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0012 #include "FWCore/Utilities/interface/CRC16.h"
0013 #include "FWCore/Utilities/interface/InputTag.h"
0014 
0015 #include "CondFormats/RPCObjects/interface/RPCAMCLink.h"
0016 #include "DataFormats/FEDRawData/interface/FEDHeader.h"
0017 #include "DataFormats/FEDRawData/interface/FEDRawData.h"
0018 #include "DataFormats/FEDRawData/interface/FEDTrailer.h"
0019 #include "DataFormats/RPCDigi/interface/RPCDigiCollection.h"
0020 #include "EventFilter/RPCRawToDigi/interface/RPCTwinMuxRecord.h"
0021 #include "EventFilter/RPCRawToDigi/interface/RPCAMCLinkEvents.h"
0022 
0023 RPCTwinMuxRawToDigi::RPCTwinMuxRawToDigi(edm::ParameterSet const &config)
0024     : calculate_crc_(config.getParameter<bool>("calculateCRC")),
0025       fill_counters_(config.getParameter<bool>("fillCounters")),
0026       bx_min_(config.getParameter<int>("bxMin")),
0027       bx_max_(config.getParameter<int>("bxMax")),
0028       es_tm_link_map_br_token_(esConsumes<RPCAMCLinkMap, RPCTwinMuxLinkMapRcd, edm::Transition::BeginRun>()),
0029       es_tm_link_map_token_(esConsumes<RPCAMCLinkMap, RPCTwinMuxLinkMapRcd>()),
0030       es_lb_link_map_token_(esConsumes<RPCLBLinkMap, RPCLBLinkMapRcd>()) {
0031   produces<RPCDigiCollection>();
0032   if (fill_counters_) {
0033     produces<RPCAMCLinkCounters>();
0034   }
0035   raw_token_ = consumes<FEDRawDataCollection>(config.getParameter<edm::InputTag>("inputTag"));
0036 }
0037 
0038 RPCTwinMuxRawToDigi::~RPCTwinMuxRawToDigi() {}
0039 
0040 void RPCTwinMuxRawToDigi::compute_crc_64bit(
0041     std::uint16_t &crc, std::uint64_t const &word) {  // overcome constness problem evf::compute_crc_64bit
0042   unsigned char const *uchars(reinterpret_cast<unsigned char const *>(&word));
0043   for (unsigned char const *uchar = uchars + 7; uchar >= uchars; --uchar) {
0044     crc = evf::compute_crc_8bit(crc, *uchar);
0045   }
0046 }
0047 
0048 void RPCTwinMuxRawToDigi::fillDescriptions(edm::ConfigurationDescriptions &descs) {
0049   edm::ParameterSetDescription desc;
0050   desc.add<edm::InputTag>("inputTag", edm::InputTag("rawDataCollector", ""));
0051   desc.add<bool>("calculateCRC", true);
0052   desc.add<bool>("fillCounters", true);
0053   desc.add<int>("bxMin", -2);
0054   desc.add<int>("bxMax", 2);
0055   descs.add("rpcTwinMuxRawToDigi", desc);
0056 }
0057 
0058 void RPCTwinMuxRawToDigi::beginRun(edm::Run const &run, edm::EventSetup const &setup) {
0059   if (es_tm_link_map_watcher_.check(setup)) {
0060     auto link_map = setup.getHandle(es_tm_link_map_br_token_);
0061     std::set<int> feds;
0062     for (auto const &tm_link : link_map->getMap()) {
0063       feds.insert(tm_link.first.getFED());
0064     }
0065     feds_.assign(feds.begin(), feds.end());
0066   }
0067 }
0068 
0069 void RPCTwinMuxRawToDigi::produce(edm::Event &event, edm::EventSetup const &setup) {
0070   // Get EventSetup Electronics Maps
0071   es_tm_link_map_ = setup.getHandle(es_tm_link_map_token_);
0072   es_lb_link_map_ = setup.getHandle(es_lb_link_map_token_);
0073 
0074   // Get RAW Data
0075   edm::Handle<FEDRawDataCollection> raw_data_collection;
0076   event.getByToken(raw_token_, raw_data_collection);
0077 
0078   std::set<std::pair<RPCDetId, RPCDigi> > rpc_digis;
0079   std::unique_ptr<RPCAMCLinkCounters> counters(new RPCAMCLinkCounters());
0080 
0081   // Loop over the FEDs
0082   for (int fed : feds_) {
0083     if (fill_counters_) {
0084       counters->add(RPCAMCLinkEvents::fed_event_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0085     }
0086 
0087     std::uint16_t crc(0xffff);
0088 
0089     FEDRawData const &raw_data = raw_data_collection->FEDData(fed);
0090     unsigned int nwords(raw_data.size() / sizeof(std::uint64_t));
0091     if (!nwords) {
0092       continue;
0093     }
0094 
0095     std::uint64_t const *word(reinterpret_cast<std::uint64_t const *>(raw_data.data()));
0096     std::uint64_t const *word_end = word + nwords;
0097 
0098     LogDebug("RPCTwinMuxRawToDigi") << "Handling FED " << fed << " with length " << nwords;
0099 
0100     // Handle the CDF Headers
0101     if (!processCDFHeaders(fed, word, word_end, crc, *counters)) {
0102       continue;
0103     }
0104 
0105     // Handle the CDF Trailers
0106     if (!processCDFTrailers(fed, nwords, word, word_end, crc, *counters)) {
0107       continue;
0108     }
0109 
0110     // Loop over the Blocks
0111     while (word < word_end) {
0112       processBlock(fed, word, word_end, crc, *counters, rpc_digis);
0113     }
0114 
0115     // Complete CRC check with trailer
0116     if (calculate_crc_) {
0117       word = word_end;
0118       word_end = reinterpret_cast<std::uint64_t const *>(raw_data.data()) + nwords - 1;
0119       for (; word < word_end; ++word) {
0120         compute_crc_64bit(crc, *word);
0121       }
0122       compute_crc_64bit(crc, (*word & 0xffffffff0000ffff));  // trailer excluding crc
0123       FEDTrailer trailer(reinterpret_cast<unsigned char const *>(word_end));
0124       if ((unsigned int)(trailer.crc()) != crc) {
0125         if (fill_counters_) {
0126           counters->add(RPCAMCLinkEvents::fed_trailer_crc_mismatch_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0127         }
0128         edm::LogWarning("RPCTwinMuxRawToDigi") << "FED Trailer CRC doesn't match for FED id " << fed;
0129       }
0130     }
0131   }
0132 
0133   putRPCDigis(event, rpc_digis);
0134   if (fill_counters_) {
0135     putCounters(event, std::move(counters));
0136   }
0137 }
0138 
0139 bool RPCTwinMuxRawToDigi::processCDFHeaders(int fed,
0140                                             std::uint64_t const *&word,
0141                                             std::uint64_t const *&word_end,
0142                                             std::uint16_t &crc,
0143                                             RPCAMCLinkCounters &counters) const {
0144   bool more_headers(true);
0145   for (; word < word_end && more_headers; ++word) {
0146     if (calculate_crc_) {
0147       compute_crc_64bit(crc, *word);
0148     }
0149 
0150     LogDebug("RPCTwinMuxRawToDigi") << "CDF Header " << std::hex << *word << std::dec;
0151     FEDHeader header(reinterpret_cast<unsigned char const *>(word));
0152     if (!header.check()) {
0153       if (fill_counters_) {
0154         counters.add(RPCAMCLinkEvents::fed_header_check_fail_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0155       }
0156       edm::LogWarning("RPCTwinMuxRawToDigi") << "FED Header check failed for FED id " << fed;
0157       ++word;
0158       break;
0159     }
0160     if (header.sourceID() != fed) {
0161       if (fill_counters_) {
0162         counters.add(RPCAMCLinkEvents::fed_header_id_mismatch_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0163       }
0164       edm::LogWarning("RPCTwinMuxRawToDigi")
0165           << "FED Header Source ID " << header.sourceID() << " does not match requested FED id " << fed;
0166       break;
0167     }
0168 
0169     // moreHeaders() not used
0170     // more_headers = header.moreHeaders();
0171     more_headers = false;
0172   }
0173 
0174   return !more_headers;
0175 }
0176 
0177 bool RPCTwinMuxRawToDigi::processCDFTrailers(int fed,
0178                                              unsigned int nwords,
0179                                              std::uint64_t const *&word,
0180                                              std::uint64_t const *&word_end,
0181                                              std::uint16_t &crc,
0182                                              RPCAMCLinkCounters &counters) const {
0183   bool more_trailers(true);
0184   for (--word_end; word_end > word && more_trailers; --word_end) {
0185     FEDTrailer trailer(reinterpret_cast<unsigned char const *>(word_end));
0186     LogDebug("RPCTwinMuxRawToDigi") << "CDF Trailer " << std::hex << *word_end << std::dec << ", length "
0187                                     << trailer.fragmentLength();
0188     if (!trailer.check()) {
0189       if (fill_counters_) {
0190         counters.add(RPCAMCLinkEvents::fed_trailer_check_fail_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0191       }
0192       edm::LogWarning("RPCTwinMuxRawToDigi") << "FED Trailer check failed for FED id " << fed;
0193       --word_end;
0194       break;
0195     }
0196     if (trailer.fragmentLength() != nwords) {
0197       if (fill_counters_) {
0198         counters.add(RPCAMCLinkEvents::fed_trailer_length_mismatch_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0199       }
0200       edm::LogWarning("RPCTwinMuxRawToDigi") << "FED Trailer length " << trailer.fragmentLength()
0201                                              << " does not match actual data size " << nwords << " for FED id " << fed;
0202       --word_end;
0203       break;
0204     }
0205 
0206     // moreTrailers() not used
0207     // more_trailers = trailer.moreTrailers();
0208     more_trailers = false;
0209   }
0210 
0211   ++word_end;
0212 
0213   return !more_trailers;
0214 }
0215 
0216 bool RPCTwinMuxRawToDigi::processBlock(int fed,
0217                                        std::uint64_t const *&word,
0218                                        std::uint64_t const *word_end,
0219                                        std::uint16_t &crc,
0220                                        RPCAMCLinkCounters &counters,
0221                                        std::set<std::pair<RPCDetId, RPCDigi> > &digis) const {
0222   // Block Header and Content
0223   rpctwinmux::BlockHeader block_header(*word);
0224   if (calculate_crc_) {
0225     compute_crc_64bit(crc, *word);
0226   }
0227   ++word;
0228 
0229   unsigned int n_amc(block_header.getNAMC());
0230   if (word + n_amc + 1 >= word_end) {
0231     if (fill_counters_) {
0232       counters.add(RPCAMCLinkEvents::fed_amc13_block_incomplete_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0233     }
0234     edm::LogWarning("RPCTwinMuxRawToDigi") << "Block can not be complete for FED " << fed;
0235     word = word_end;
0236     return false;
0237   }
0238 
0239   std::vector<std::pair<unsigned int, unsigned int> > amc_size_map;
0240   for (unsigned int amc = 0; amc < n_amc; ++amc) {
0241     LogDebug("RPCTwinMuxRawToDigi") << "Block AMC " << amc;
0242     rpctwinmux::BlockAMCContent amc_content(*word);
0243     if (calculate_crc_) {
0244       compute_crc_64bit(crc, *word);
0245     }
0246     ++word;
0247 
0248     amc_size_map.push_back(std::make_pair(amc_content.getAMCNumber(), amc_content.getSize()));
0249     if (!amc_content.isValid()) {
0250       if (fill_counters_) {
0251         counters.add(RPCAMCLinkEvents::amc_amc13_evc_bc_invalid_, RPCAMCLink(fed, amc_content.getAMCNumber()));
0252       }
0253       edm::LogWarning("RPCTwinMuxRawToDigi")
0254           << "BlockAMCContent is reporting an invalid "
0255           << "Event Counter or Bunch Counter for FED " << fed << ", AMC " << amc_content.getAMCNumber();
0256     }
0257   }
0258 
0259   for (std::pair<unsigned int, unsigned int> const &amc_size : amc_size_map) {
0260     processTwinMux(fed, amc_size.first, amc_size.second, word, word_end, crc, counters, digis);
0261   }
0262 
0263   if (word < word_end) {
0264     rpctwinmux::BlockTrailer block_trailer(*word);
0265     if (calculate_crc_) {
0266       compute_crc_64bit(crc, *word);
0267     }
0268     ++word;
0269     return true;
0270   } else {
0271     return false;
0272   }
0273 }
0274 
0275 bool RPCTwinMuxRawToDigi::processTwinMux(int fed,
0276                                          unsigned int amc_number,
0277                                          unsigned int size,
0278                                          std::uint64_t const *&word,
0279                                          std::uint64_t const *word_end,
0280                                          std::uint16_t &crc,
0281                                          RPCAMCLinkCounters &counters,
0282                                          std::set<std::pair<RPCDetId, RPCDigi> > &digis) const {
0283   LogDebug("RPCTwinMuxRawToDigi") << "TwinMux AMC#" << amc_number << ", size " << size;
0284   if (!size) {
0285     return true;
0286   }
0287   if (amc_number > (unsigned int)RPCAMCLink::max_amcnumber_) {
0288     if (fill_counters_) {
0289       counters.add(RPCAMCLinkEvents::fed_amc13_amc_number_invalid_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0290     }
0291     edm::LogWarning("RPCTwinMuxRawToDigi") << "Invalid AMC Number " << amc_number << " for FED " << fed;
0292     if (calculate_crc_) {
0293       for (; size > 0; --size, ++word) {
0294         compute_crc_64bit(crc, *word);
0295       }
0296     } else {
0297       word += size;
0298     }
0299     return false;
0300   }
0301   if (word + size >= word_end || size < 3) {
0302     if (fill_counters_) {
0303       counters.add(RPCAMCLinkEvents::amc_payload_incomplete_, RPCAMCLink(fed, amc_number));
0304     }
0305     edm::LogWarning("RPCTwinMuxRawToDigi")
0306         << "TwinMux Data can not be complete for FED " << fed << " AMC #" << amc_number;
0307     if (calculate_crc_) {
0308       for (; size > 0; --size, ++word) {
0309         compute_crc_64bit(crc, *word);
0310       }
0311     } else {
0312       word += size;
0313     }
0314     return false;
0315   }
0316 
0317   rpctwinmux::TwinMuxHeader header(word);
0318   unsigned int bx_counter(header.getBXCounter());
0319   if (calculate_crc_) {
0320     compute_crc_64bit(crc, *word);
0321     ++word;
0322     compute_crc_64bit(crc, *word);
0323     ++word;
0324   } else {
0325     word += 2;
0326   }
0327   size -= 2;
0328 
0329   if (amc_number != header.getAMCNumber()) {
0330     if (fill_counters_) {
0331       counters.add(RPCAMCLinkEvents::amc_number_mismatch_, RPCAMCLink(fed, amc_number));
0332     }
0333     edm::LogWarning("RPCTwinMuxRawToDigi")
0334         << "AMC Number inconsistent in TwinMuxHeader vs BlockAMCContent: " << header.getAMCNumber() << " vs "
0335         << amc_number;
0336     if (calculate_crc_) {
0337       for (; size > 0; --size, ++word) {
0338         compute_crc_64bit(crc, *word);
0339       }
0340     } else {
0341       word += size;
0342     }
0343     return false;
0344   }
0345 
0346   int bx_min(bx_min_), bx_max(bx_max_);
0347   if (header.hasRPCBXWindow()) {
0348     bx_min = std::max(bx_min, header.getRPCBXMin());
0349     bx_max = std::min(bx_max, header.getRPCBXMax());
0350     LogDebug("RPCTwinMuxRawToDigi") << "BX range set to " << bx_min << ", " << bx_max;
0351   }
0352 
0353   bool has_first_rpc_word(false);
0354   rpctwinmux::RPCRecord rpc_record;
0355   for (; size > 1; --size, ++word) {
0356     if (calculate_crc_) {
0357       compute_crc_64bit(crc, *word);
0358     }
0359     unsigned int type(rpctwinmux::TwinMuxRecord::getType(*word));
0360     LogDebug("RPCTwinMuxRawToDigi") << "TwinMux data type " << std::hex << type << std::dec;
0361     if (type == rpctwinmux::TwinMuxRecord::rpc_first_type_) {
0362       if (has_first_rpc_word) {
0363         processRPCRecord(fed, amc_number, bx_counter, rpc_record, counters, digis, bx_min, bx_max, 0, 1);
0364       }
0365       rpc_record.reset();
0366       rpc_record.set(0, *word);
0367       has_first_rpc_word = true;
0368     } else if (type == rpctwinmux::TwinMuxRecord::rpc_second_type_) {
0369       if (!has_first_rpc_word) {
0370         edm::LogWarning("RPCTwinMuxRawToDigi") << "Received second RPC word without first";
0371       } else {
0372         rpc_record.set(1, *word);
0373         processRPCRecord(fed, amc_number, bx_counter, rpc_record, counters, digis, bx_min, bx_max, 0, 4);
0374         has_first_rpc_word = false;
0375       }
0376     }
0377   }
0378   if (has_first_rpc_word) {
0379     processRPCRecord(fed, amc_number, bx_counter, rpc_record, counters, digis, bx_min, bx_max, 0, 1);
0380   }
0381 
0382   rpctwinmux::TwinMuxTrailer trailer(*word);
0383   LogDebug("RPCTwinMuxRawToDigi") << "TwinMux Trailer " << std::hex << *word << std::dec;
0384   if (calculate_crc_) {
0385     compute_crc_64bit(crc, *word);
0386   }
0387   ++word;
0388   return true;
0389 }
0390 
0391 void RPCTwinMuxRawToDigi::processRPCRecord(int fed,
0392                                            unsigned int amc_number,
0393                                            unsigned int bx_counter,
0394                                            rpctwinmux::RPCRecord const &record,
0395                                            RPCAMCLinkCounters &counters,
0396                                            std::set<std::pair<RPCDetId, RPCDigi> > &digis,
0397                                            int bx_min,
0398                                            int bx_max,
0399                                            unsigned int link,
0400                                            unsigned int link_max) const {
0401   LogDebug("RPCTwinMuxRawToDigi") << "RPCRecord " << std::hex << record.getRecord()[0] << ", " << record.getRecord()[1]
0402                                   << std::dec << std::endl;
0403   int bx_offset(record.getBXOffset());
0404   RPCAMCLink tm_link(fed, amc_number);
0405   for (; link <= link_max; ++link) {
0406     tm_link.setAMCInput(link);
0407     rpctwinmux::RPCLinkRecord link_record(record.getRPCLinkRecord(link));
0408 
0409     if (link_record.isError()) {
0410       if (fill_counters_ && bx_offset == 0) {
0411         counters.add(RPCAMCLinkEvents::input_link_error_, tm_link);
0412       }
0413       LogDebug("RPCTwinMuxRawToDigi") << "Link in error for " << tm_link;
0414       continue;
0415     } else if (!link_record.isAcknowledge()) {
0416       if (fill_counters_ && bx_offset == 0) {
0417         counters.add(RPCAMCLinkEvents::input_link_ack_fail_, tm_link);
0418       }
0419       LogDebug("RPCTwinMuxRawToDigi") << "Link without acknowledge for " << tm_link;
0420       continue;
0421     }
0422 
0423     if (!link_record.getPartitionData()) {
0424       continue;
0425     }
0426 
0427     int bx(bx_offset - (int)(link_record.getDelay()));
0428     LogDebug("RPCTwinMuxRawToDigi") << "RPC BX " << bx << " for offset " << bx_offset;
0429 
0430     if (fill_counters_ && bx == 0 && link_record.isEOD()) {  // EOD comes at the last delay
0431       counters.add(RPCAMCLinkEvents::input_eod_, tm_link);
0432     }
0433 
0434     RPCAMCLinkMap::map_type::const_iterator tm_link_it = es_tm_link_map_->getMap().find(tm_link);
0435     if (tm_link_it == es_tm_link_map_->getMap().end()) {
0436       if (fill_counters_ && bx_offset == 0) {
0437         counters.add(RPCAMCLinkEvents::amc_link_invalid_, RPCAMCLink(fed, amc_number));
0438       }
0439       LogDebug("RPCTwinMuxRawToDigi") << "Skipping unknown TwinMuxLink " << tm_link;
0440       continue;
0441     }
0442 
0443     RPCLBLink lb_link = tm_link_it->second;
0444 
0445     if (link_record.getLinkBoard() > (unsigned int)RPCLBLink::max_linkboard_) {
0446       if (fill_counters_ && bx_offset == 0) {
0447         counters.add(RPCAMCLinkEvents::input_lb_invalid_, tm_link);
0448       }
0449       LogDebug("RPCTwinMuxRawToDigi") << "Skipping invalid LinkBoard " << link_record.getLinkBoard() << " for record "
0450                                       << link << " (" << std::hex << link_record.getRecord() << " in "
0451                                       << record.getRecord()[0] << ':' << record.getRecord()[1] << std::dec << " from "
0452                                       << tm_link;
0453       continue;
0454     }
0455 
0456     if (link_record.getConnector() > (unsigned int)RPCLBLink::max_connector_) {
0457       if (fill_counters_ && bx_offset == 0) {
0458         counters.add(RPCAMCLinkEvents::input_connector_invalid_, tm_link);
0459       }
0460       LogDebug("RPCTwinMuxRawToDigi") << "Skipping invalid Connector " << link_record.getConnector() << " for record "
0461                                       << link << " (" << std::hex << link_record.getRecord() << " in "
0462                                       << record.getRecord()[0] << ':' << record.getRecord()[1] << std::dec << ") from "
0463                                       << tm_link;
0464       continue;
0465     }
0466 
0467     lb_link.setLinkBoard(link_record.getLinkBoard());
0468     lb_link.setConnector(link_record.getConnector());
0469 
0470     RPCLBLinkMap::map_type::const_iterator lb_link_it = es_lb_link_map_->getMap().find(lb_link);
0471     if (lb_link_it == es_lb_link_map_->getMap().end()) {
0472       if (fill_counters_ && bx_offset == 0) {
0473         counters.add(RPCAMCLinkEvents::input_connector_not_used_, tm_link);
0474       }
0475       LogDebug("RPCTwinMuxRawToDigi") << "Could not find " << lb_link << " for record " << link << " (" << std::hex
0476                                       << link_record.getRecord() << " in " << record.getRecord()[0] << ':'
0477                                       << record.getRecord()[1] << std::dec << ") from " << tm_link;
0478       continue;
0479     }
0480 
0481     if (bx < bx_min || bx > bx_max) {
0482       continue;
0483     }
0484 
0485     if (fill_counters_ && bx == 0) {
0486       counters.add(RPCAMCLinkEvents::amc_event_, RPCAMCLink(fed, amc_number));
0487       counters.add(RPCAMCLinkEvents::input_event_, tm_link);
0488     }
0489 
0490     RPCFebConnector const &feb_connector(lb_link_it->second);
0491     RPCDetId det_id(feb_connector.getRPCDetId());
0492     unsigned int channel_offset(link_record.getPartition() ? 9 : 1);  // 1-16
0493     std::uint8_t data(link_record.getPartitionData());
0494 
0495     for (unsigned int channel = 0; channel < 8; ++channel) {
0496       if (data & (0x1 << channel)) {
0497         unsigned int strip(feb_connector.getStrip(channel + channel_offset));
0498         if (strip) {
0499           digis.insert(std::pair<RPCDetId, RPCDigi>(det_id, RPCDigi(strip, bx)));
0500           LogDebug("RPCTwinMuxRawToDigi") << "RPCDigi " << det_id.rawId() << ", " << strip << ", " << bx;
0501         }
0502       }
0503     }
0504 
0505     // rpctwinmux::RPCBXRecord checks postponed: not implemented in firmware as planned and tbd if design or firmware should change
0506   }
0507 }
0508 
0509 void RPCTwinMuxRawToDigi::putRPCDigis(edm::Event &event, std::set<std::pair<RPCDetId, RPCDigi> > const &digis) {
0510   std::unique_ptr<RPCDigiCollection> rpc_digi_collection(new RPCDigiCollection());
0511   RPCDetId rpc_det_id;
0512   std::vector<RPCDigi> local_digis;
0513   for (std::pair<RPCDetId, RPCDigi> const &rpc_digi : digis) {
0514     LogDebug("RPCTwinMuxRawToDigi") << "RPCDigi " << rpc_digi.first.rawId() << ", " << rpc_digi.second.strip() << ", "
0515                                     << rpc_digi.second.bx();
0516     if (rpc_digi.first != rpc_det_id) {
0517       if (!local_digis.empty()) {
0518         rpc_digi_collection->put(RPCDigiCollection::Range(local_digis.begin(), local_digis.end()), rpc_det_id);
0519         local_digis.clear();
0520       }
0521       rpc_det_id = rpc_digi.first;
0522     }
0523     local_digis.push_back(rpc_digi.second);
0524   }
0525   if (!local_digis.empty()) {
0526     rpc_digi_collection->put(RPCDigiCollection::Range(local_digis.begin(), local_digis.end()), rpc_det_id);
0527   }
0528 
0529   event.put(std::move(rpc_digi_collection));
0530 }
0531 
0532 void RPCTwinMuxRawToDigi::putCounters(edm::Event &event, std::unique_ptr<RPCAMCLinkCounters> counters) {
0533   event.put(std::move(counters));
0534 }
0535 
0536 #include "FWCore/Framework/interface/MakerMacros.h"
0537 DEFINE_FWK_MODULE(RPCTwinMuxRawToDigi);