CMS 3D CMS Logo

CSCTMBHeader.cc
Go to the documentation of this file.
15 #include <cmath>
16 #include <cstring> // memcpy
17 
18 #ifdef LOCAL_UNPACK
19 bool CSCTMBHeader::debug = false;
20 #else
21 std::atomic<bool> CSCTMBHeader::debug{false};
22 #endif
23 
24 CSCTMBHeader::CSCTMBHeader(int firmwareVersion, int firmwareRevision)
25  : theHeaderFormat(), theFirmwareVersion(firmwareVersion) {
26  if (firmwareVersion == 2020) {
27  if ((firmwareRevision < 0x4000) && (firmwareRevision > 0x0)) { /* New (O)TMB firmware revision format */
28  bool isGEM_fw = false;
29  bool isCCLUT_HMT_fw = false;
30  bool isOTMB_Run2_fw = false;
31  bool isTMB_Run3_fw = false;
32  bool isTMB_Run2_fw = false;
33  bool isTMB_hybrid_fw = false;
34  bool isRun2_df = false;
35  unsigned df_version = (firmwareRevision >> 9) & 0xF; // 4-bits Data Format version
36  unsigned major_ver = (firmwareRevision >> 5) & 0xF; // 4-bits major version part
37  // unsigned minor_ver = firmwareRevision & 0x1F; // 5-bits minor version part
38  switch (df_version) {
39  case 0x4:
40  isTMB_hybrid_fw = true;
41  break;
42  case 0x3:
43  isGEM_fw = true;
44  break;
45  case 0x2:
46  isCCLUT_HMT_fw = true;
47  break;
48  case 0x1:
49  isOTMB_Run2_fw = true;
50  break;
51  case 0x0:
52  if (major_ver == 1)
53  isTMB_Run2_fw = true;
54  else
55  isTMB_Run3_fw = true;
56  break;
57  default:
58  isGEM_fw = true;
59  }
60  if (major_ver == 1) {
61  isRun2_df = true;
62  }
63 
64  if (isGEM_fw) {
65  if (isRun2_df) {
66  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_Run2(firmwareRevision));
67  } else {
68  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_GEM());
69  }
70  } else if (isCCLUT_HMT_fw) {
71  if (isRun2_df) {
72  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_Run2(firmwareRevision));
73  } else {
74  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_CCLUT());
75  }
76  } else if (isOTMB_Run2_fw || isTMB_Run2_fw || isRun2_df) {
77  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_Run2(firmwareRevision));
78  } else if (isTMB_Run3_fw) {
79  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_CCLUT());
80  } else if (isTMB_hybrid_fw) {
81  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_TMB());
82  }
83  }
84  } else if (firmwareVersion == 2013) {
85  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2013());
86  } else if (firmwareVersion == 2006) {
87  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2006());
88  } else if (firmwareVersion == 2007) {
89  /* Checks for TMB2007 firmware revisions ranges to detect data format
90  * rev.0x50c3 - first revision with changed format
91  * rev.0x42D5 - oldest known from 06/21/2007
92  * There is 4-bits year value rollover in revision number (0 in 2016)
93  */
94  if ((firmwareRevision >= 0x50c3) || (firmwareRevision < 0x42D5)) {
95  // if (firmwareRevision >= 0x7a76) // First OTMB firmware revision with 2013 format
96  /* Revisions > 0x6000 - OTMB firmwares, < 0x42D5 - new TMB revisions in 2016 */
97  if ((firmwareRevision >= 0x6000) || (firmwareRevision < 0x42D5)) {
98  bool isGEMfirmware = false;
99  /* There are OTMB2013 firmware versions exist, which reports firmwareRevision code = 0x0 */
100  if ((firmwareRevision < 0x4000) && (firmwareRevision > 0x0)) { /* New (O)TMB firmware revision format */
101  if (((firmwareRevision >> 9) & 0x3) == 0x3)
102  isGEMfirmware = true;
103  if (isGEMfirmware) {
104  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_GEM());
105  } else {
106  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2013());
107  }
108  }
109  } else {
110  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2007_rev0x50c3());
111  }
112  } else {
113  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2007());
114  }
115  } else {
116  edm::LogError("CSCTMBHeader|CSCRawToDigi") << "failed to determine TMB firmware version!!";
117  }
118 }
119 
120 //CSCTMBHeader::CSCTMBHeader(const CSCTMBStatusDigi & digi) {
121 // CSCTMBHeader(digi.header());
122 //}
123 
124 CSCTMBHeader::CSCTMBHeader(const unsigned short *buf) : theHeaderFormat() {
126  if (buf[0] == 0xDB0C) {
127  theFirmwareVersion = 2007;
128  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2007(buf));
129  /* Checks for TMB2007 firmware revisions ranges to detect data format
130  * rev.0x50c3 - first revision with changed format
131  * rev.0x42D5 - oldest known from 06/21/2007
132  * There is 4-bits year value rollover in revision number (0 in 2016)
133  */
134  if ((theHeaderFormat->firmwareRevision() >= 0x50c3) || (theHeaderFormat->firmwareRevision() < 0x42D5)) {
135  // if (theHeaderFormat->firmwareRevision() >= 0x7a76) // First OTMB firmware revision with 2013 format
136  /* Revisions > 0x6000 - OTMB firmwares, < 0x42D5 - new TMB revisions in 2016 */
137  if ((theHeaderFormat->firmwareRevision() >= 0x6000) || (theHeaderFormat->firmwareRevision() < 0x42D5)) {
138  theFirmwareVersion = 2013;
139  bool isGEM_fw = false;
140  bool isCCLUT_HMT_fw = false;
141  bool isOTMB_Run2_fw = false;
142  bool isTMB_Run3_fw = false;
143  bool isTMB_Run2_fw = false;
144  bool isTMB_hybrid_fw = false;
145  bool isRun2_df = false;
146  unsigned firmwareRevision = theHeaderFormat->firmwareRevision();
147  /* There are OTMB2013 firmware versions exist, which reports firmwareRevision code = 0x0 */
148  if ((firmwareRevision < 0x4000) && (firmwareRevision > 0x0)) { /* New (O)TMB firmware revision format */
149  theFirmwareVersion = 2020;
150  unsigned df_version = (firmwareRevision >> 9) & 0xF; // 4-bits Data Format version
151  unsigned major_ver = (firmwareRevision >> 5) & 0xF; // 4-bits major version part
152  // unsigned minor_ver = firmwareRevision & 0x1F; // 5-bits minor version part
153  switch (df_version) {
154  case 0x4:
155  isTMB_hybrid_fw = true;
156  break;
157  case 0x3:
158  isGEM_fw = true;
159  break;
160  case 0x2:
161  isCCLUT_HMT_fw = true;
162  break;
163  case 0x1:
164  isOTMB_Run2_fw = true;
165  break;
166  case 0x0:
167  if (major_ver == 1)
168  isTMB_Run2_fw = true;
169  else
170  isTMB_Run3_fw = true;
171  break;
172  default:
173  isGEM_fw = true;
174  }
175  if (major_ver == 1) {
176  isRun2_df = true;
177  }
178  }
179  if (theFirmwareVersion == 2020) {
180  if (isGEM_fw) {
181  if (isRun2_df) {
182  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_Run2(buf));
183  } else {
184  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_GEM(buf));
185  }
186  } else if (isCCLUT_HMT_fw) {
187  if (isRun2_df) {
188  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_Run2(buf));
189  } else {
190  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_CCLUT(buf));
191  }
192  } else if (isOTMB_Run2_fw || isTMB_Run2_fw || isRun2_df) {
193  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_Run2(buf));
194  } else if (isTMB_Run3_fw) {
195  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_CCLUT(buf));
196  } else if (isTMB_hybrid_fw) {
197  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2020_TMB(buf));
198  }
199 
200  } else {
201  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2013(buf));
202  }
203 
204  } else {
205  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2007_rev0x50c3(buf));
206  }
207  }
208 
209  } else if (buf[0] == 0x6B0C) {
210  theFirmwareVersion = 2006;
211  theHeaderFormat = std::shared_ptr<CSCVTMBHeaderFormat>(new CSCTMBHeader2006(buf));
212  } else {
213  edm::LogError("CSCTMBHeader|CSCRawToDigi") << "failed to determine TMB firmware version!!";
214  }
215 }
216 
217 /*
218 void CSCTMBHeader::swapCLCTs(CSCCLCTDigi& digi1, CSCCLCTDigi& digi2)
219 {
220  bool me11 = (theChamberId.station() == 1 &&
221  (theChamberId.ring() == 1 || theChamberId.ring() == 4));
222  if (!me11) return;
223 
224  int cfeb1 = digi1.getCFEB();
225  int cfeb2 = digi2.getCFEB();
226  if (cfeb1 != cfeb2) return;
227 
228  bool me1a = (cfeb1 == 4);
229  bool me1b = (cfeb1 != 4);
230  bool zplus = (theChamberId.endcap() == 1);
231 
232  if ( (me1a && zplus) || (me1b && !zplus)) {
233  // Swap CLCTs if they have the same quality and pattern # (priority
234  // has to be given to the lower key).
235  if (digi1.getQuality() == digi2.getQuality() &&
236  digi1.getPattern() == digi2.getPattern()) {
237  CSCCLCTDigi temp = digi1;
238  digi1 = digi2;
239  digi2 = temp;
240 
241  // Also re-number them.
242  digi1.setTrknmb(1);
243  digi2.setTrknmb(2);
244  }
245  }
246 }
247 */
248 
249 //FIXME Pick which LCT goes first
250 void CSCTMBHeader::add(const std::vector<CSCCLCTDigi> &digis) {
251  // sort???
252  if (!digis.empty()) {
253  addCLCT0(digis[0]);
254  }
255  if (digis.size() > 1)
256  addCLCT1(digis[1]);
257 }
258 
259 void CSCTMBHeader::add(const std::vector<CSCCorrelatedLCTDigi> &digis) {
260  // sort???
261  if (!digis.empty())
262  addCorrelatedLCT0(digis[0]);
263  if (digis.size() > 1)
264  addCorrelatedLCT1(digis[1]);
265 }
266 
267 void CSCTMBHeader::add(const std::vector<CSCShowerDigi> &digis) {
268  if (!digis.empty())
269  theHeaderFormat->addShower(digis[0]);
270 }
271 
273  CSCTMBHeader2007 *result = dynamic_cast<CSCTMBHeader2007 *>(theHeaderFormat.get());
274  if (result == nullptr) {
275  throw cms::Exception("Could not get 2007 TMB header format");
276  }
277  return *result;
278 }
279 
282  if (result == nullptr) {
283  throw cms::Exception("Could not get 2007 rev0x50c3 TMB header format");
284  }
285  return *result;
286 }
287 
289  CSCTMBHeader2013 *result = dynamic_cast<CSCTMBHeader2013 *>(theHeaderFormat.get());
290  if (result == nullptr) {
291  throw cms::Exception("Could not get 2013 TMB header format");
292  }
293  return *result;
294 }
295 
298  if (result == nullptr) {
299  throw cms::Exception("Could not get 2020 TMB Run3 header format");
300  }
301  return *result;
302 }
303 
306  if (result == nullptr) {
307  throw cms::Exception("Could not get 2020 (O)TMB CCLUT header format");
308  }
309  return *result;
310 }
311 
314  if (result == nullptr) {
315  throw cms::Exception("Could not get 2020 (O)TMB GEM header format");
316  }
317  return *result;
318 }
319 
322  if (result == nullptr) {
323  throw cms::Exception("Could not get 2020 (O)TMB legacy Run2 header format");
324  }
325  return *result;
326 }
327 
329  CSCTMBHeader2006 *result = dynamic_cast<CSCTMBHeader2006 *>(theHeaderFormat.get());
330  if (result == nullptr) {
331  throw cms::Exception("Could not get 2006 TMB header format");
332  }
333  return *result;
334 }
335 
336 void CSCTMBHeader::selfTest(int firmwareVersion, int firmwareRevision) {
337  constexpr bool debug = false;
338 
339  // tests packing and unpacking
340  for (int station = 1; station <= 4; ++station) {
341  for (int iendcap = 1; iendcap <= 2; ++iendcap) {
342  CSCDetId detId(iendcap, station, 1, 1, 0);
343 
344  // the next-to-last is the BX, which only gets
345  // saved in two bits and must be the same for clct0 and clct1.
346  //CSCCLCTDigi clct0(1, 1, 4, 0, 0, 30, 3, 0, 1); // valid for 2006
347  // In 2007 firmware, there are no distrips, so the 4th argument (strip
348  // type) should always be set to 1 (halfstrips).
349  CSCCLCTDigi clct0(1, 1, 4, 1, 0, 30, 4, 2, 1); // valid for 2007
350  CSCCLCTDigi clct1(1, 1, 3, 1, 1, 31, 1, 2, 2);
351 
352  // BX of LCT (8th argument) is 1-bit word (the least-significant bit
353  // of ALCT's bx).
354  CSCCorrelatedLCTDigi lct0(1, 1, 2, 10, 98, 5, 0, 1, 0, 0, 0, 0);
355  CSCCorrelatedLCTDigi lct1(2, 1, 2, 20, 15, 9, 1, 0, 0, 0, 0, 0);
356 
357  // Use Run3 format digis for TMB firmwareVersion 2020
358  // and revision codes for MEx1 CCLUT, ME11 CCLUT/GEM
359  if (firmwareVersion >= 2020) {
360  bool isGEM_fw = false;
361  bool isCCLUT_HMT_fw = false;
362  bool isOTMB_Run2_fw = false;
363  bool isTMB_Run3_fw = false;
364  bool isTMB_Run2_fw = false;
365  bool isTMB_hybrid_fw = false;
366  bool isRun2_df = false;
367  unsigned df_version = (firmwareRevision >> 9) & 0xF; // 4-bits Data Format version
368  unsigned major_ver = (firmwareRevision >> 5) & 0xF; // 4-bits major version part
369  // unsigned minor_ver = firmwareRevision & 0x1F; // 5-bits minor version part
370  switch (df_version) {
371  case 0x4:
372  isTMB_hybrid_fw = true;
373  break;
374  case 0x3:
375  isGEM_fw = true;
376  break;
377  case 0x2:
378  isCCLUT_HMT_fw = true;
379  break;
380  case 0x1:
381  isOTMB_Run2_fw = true;
382  break;
383  case 0x0:
384  if (major_ver == 1)
385  isTMB_Run2_fw = true;
386  else
387  isTMB_Run3_fw = true;
388  break;
389  default:
390  isGEM_fw = true;
391  }
392  if (major_ver == 1) {
393  isRun2_df = true;
394  }
395  if ((isGEM_fw || isCCLUT_HMT_fw || isTMB_Run3_fw) && !isRun2_df && !isOTMB_Run2_fw && !isTMB_Run2_fw &&
396  !isTMB_hybrid_fw) {
397  clct0 = CSCCLCTDigi(
398  1, 6, 6, 1, 0, (120 % 32), (120 / 32), 2, 1, 3, 0xebf, CSCCLCTDigi::Version::Run3, true, false, 2, 6);
399  clct1 = CSCCLCTDigi(
400  1, 6, 3, 1, 1, (132 % 32), (132 / 32), 2, 2, 3, 0xe54, CSCCLCTDigi::Version::Run3, false, true, 1, 15);
401  }
402  if ((isGEM_fw || isCCLUT_HMT_fw || isTMB_Run3_fw) && !isRun2_df && !isOTMB_Run2_fw && !isTMB_Run2_fw &&
403  !isTMB_hybrid_fw) {
404  lct0 = CSCCorrelatedLCTDigi(
405  1, 1, 3, 85, 120, 6, 0, 0, 0, 0, 0, 0, CSCCorrelatedLCTDigi::Version::Run3, true, false, 2, 6);
406  lct1 = CSCCorrelatedLCTDigi(
407  2, 1, 2, 81, 132, 3, 1, 0, 0, 0, 0, 0, CSCCorrelatedLCTDigi::Version::Run3, false, true, 0, 15);
408  }
409  if (isTMB_hybrid_fw) {
410  lct0 = CSCCorrelatedLCTDigi(
411  1, 1, 3, 85, 120, 6, 0, 0, 0, 0, 0, 0, CSCCorrelatedLCTDigi::Version::Run3, false, false, 0, 0);
412  lct1 = CSCCorrelatedLCTDigi(
413  2, 1, 2, 81, 132, 3, 1, 0, 0, 0, 0, 0, CSCCorrelatedLCTDigi::Version::Run3, false, false, 0, 0);
414  }
415  }
416 
417  CSCTMBHeader tmbHeader(firmwareVersion, firmwareRevision);
418  tmbHeader.addCLCT0(clct0);
419  tmbHeader.addCLCT1(clct1);
420  tmbHeader.addCorrelatedLCT0(lct0);
421  tmbHeader.addCorrelatedLCT1(lct1);
422  std::vector<CSCCLCTDigi> clcts = tmbHeader.CLCTDigis(detId.rawId());
423  // guess they got reordered
424  assert(cscPackerCompare(clcts[0], clct0));
425  assert(cscPackerCompare(clcts[1], clct1));
426  if (debug) {
427  std::cout << "Match for: " << clct0 << "\n";
428  std::cout << " " << clct1 << "\n \n";
429  }
430 
431  std::vector<CSCCorrelatedLCTDigi> lcts = tmbHeader.CorrelatedLCTDigis(detId.rawId());
432  assert(cscPackerCompare(lcts[0], lct0));
433  assert(cscPackerCompare(lcts[1], lct1));
434  if (debug) {
435  std::cout << "Match for: " << lct0 << "\n";
436  std::cout << " " << lct1 << "\n";
437  }
438 
439  // try packing and re-packing, to make sure they're the same
440  unsigned short int *data = tmbHeader.data();
441  CSCTMBHeader newHeader(data);
442  clcts = newHeader.CLCTDigis(detId.rawId());
443  assert(cscPackerCompare(clcts[0], clct0));
444  assert(cscPackerCompare(clcts[1], clct1));
445  lcts = newHeader.CorrelatedLCTDigis(detId.rawId());
446  assert(cscPackerCompare(lcts[0], lct0));
447  assert(cscPackerCompare(lcts[1], lct1));
448  }
449  }
450 }
451 
452 std::ostream &operator<<(std::ostream &os, const CSCTMBHeader &hdr) {
453  hdr.theHeaderFormat->print(os);
454  return os;
455 }
CSCTMBHeader2007_rev0x50c3 tmbHeader2007_rev0x50c3() const
CSCTMBHeader2020_TMB tmbHeader2020_TMB() const
int theFirmwareVersion
Definition: CSCTMBHeader.h:156
std::shared_ptr< CSCVTMBHeaderFormat > theHeaderFormat
Definition: CSCTMBHeader.h:155
CSCTMBHeader2020_Run2 tmbHeader2020_Run2() const
void addCorrelatedLCT0(const CSCCorrelatedLCTDigi &digi)
Definition: CSCTMBHeader.h:127
void add(const std::vector< CSCCLCTDigi > &digis)
these methods need more brains to figure which one goes first
Log< level::Error, false > LogError
assert(be >=bs)
void addCorrelatedLCT1(const CSCCorrelatedLCTDigi &digi)
Definition: CSCTMBHeader.h:128
void addCLCT1(const CSCCLCTDigi &digi)
Definition: CSCTMBHeader.h:124
unsigned short * data()
Definition: CSCTMBHeader.h:115
static std::atomic< bool > debug
Definition: CSCTMBHeader.h:152
std::ostream & operator<<(std::ostream &os, const CSCTMBHeader &hdr)
std::vector< CSCCLCTDigi > CLCTDigis(uint32_t idlayer)
returns CLCT digis
Definition: CSCTMBHeader.h:102
void addCLCT0(const CSCCLCTDigi &digi)
for data packing
Definition: CSCTMBHeader.h:123
bool cscPackerCompare(const T &t1, const T &t2)
static void selfTest(int firmwwareVersion, int firmwareRevision)
tests that packing and unpacking give same results
CSCTMBHeader2006 tmbHeader2006() const
CSCTMBHeader2020_GEM tmbHeader2020_GEM() const
CSCTMBHeader(int firmwareVersion, int firmwareRevision)
Definition: CSCTMBHeader.cc:24
CSCTMBHeader2007 tmbHeader2007() const
will throw if the cast fails
std::vector< CSCCorrelatedLCTDigi > CorrelatedLCTDigis(uint32_t idlayer) const
returns CorrelatedLCT digis
Definition: CSCTMBHeader.h:105
CSCTMBHeader2020_CCLUT tmbHeader2020_CCLUT() const
CSCTMBHeader2013 tmbHeader2013() const