CbmRoot
Loading...
Searching...
No Matches
CbmStsUnpackAlgoLegacy.cxx
Go to the documentation of this file.
1/* Copyright (C) 2019-2021 Fair GmbH, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Pierre-Alain Loizeau, Dominik Smith [committer] */
4
5
7
9//#include "CbmFormatMsHeaderPrintout.h"
10#include "CbmMcbm2018StsPar.h"
11#include "TCanvas.h"
12#include "TH1.h"
13#include "TH2.h"
14#include "TList.h"
15#include "TProfile.h"
16#include "TROOT.h"
17#include "TString.h"
18
19#include <Logger.h>
20
21#include <fstream>
22#include <iomanip>
23#include <iostream>
24
25#include <stdint.h>
26
27// -------------------------------------------------------------------------
28
30 : CbmStsUnpackAlgoBase("CbmStsUnpackAlgoLegacy")
31 ,
33 fvbMaskedComponents()
34 , fUnpackPar(nullptr)
35 , fuNbFebs(0)
36 , fDpbIdIndexMap()
37 , fviFebType()
38 , fviFebAddress()
39 , fviFebSide()
40 , fvdFebAdcGain()
41 , fvdFebAdcOffs()
42 , fdTimeOffsetNs(0.0)
43 , fbUseChannelMask(false)
44 , fvvbMaskedChannels()
45 , fulCurrentMsIdx(0)
46 , fuCurrDpbIdx(0)
47 , fvulCurrentTsMsb()
48 , fdStartTime(0.0)
49 , fdStartTimeMsSz(-1.0)
50 , ftStartTimeUnix(std::chrono::steady_clock::now())
51 , fvmHitsInMs()
52 , fvvusLastTsChan()
53 , fvvusLastAdcChan()
54 , fvvuLastTsMsbChan()
55 , fvvusLastTsMsbCycleChan()
56{
57}
58
65
66// -------------------------------------------------------------------------
68{
69 LOG(info) << "Initializing mCBM STS 2019 unpacker algo";
70 return true;
71}
72
73// -------------------------------------------------------------------------
75
76
77// ---- initParSet(FairParGenericSet* parset) ----
78Bool_t CbmStsUnpackAlgoLegacy::initParSet(FairParGenericSet* parset)
79{
80 LOG(info) << fName << "::initParSet - for container " << parset->ClassName();
81 if (parset->IsA() == CbmMcbm2018StsPar::Class()) return initParSet(static_cast<CbmMcbm2018StsPar*>(parset));
82
83 // If we do not know the derived ParSet class we return false
84 LOG(error)
85 << fName << "::initParSet - for container " << parset->ClassName()
86 << " failed, since CbmStsUnpackAlgoLegacy::initParSet() does not know the derived ParSet and what to do with it!";
87 return kFALSE;
88}
89
90// ---- initParSet(CbmMcbm2018StsPar* parset) ----
92{
93 fUnpackPar = parset;
94 bool initOK = InitParameters();
95
96 if (fMonitor) initOK &= fMonitor->Init(parset);
97
98 return initOK;
99}
100
101// -------------------------------------------------------------------------
103{
104 //Type of each module: 0 for connectors on the right, 1 for connectors on the left
105 std::vector<int32_t> viModuleType;
106
107 // STS address for the first strip of each module
108 std::vector<int32_t> viModAddress;
109
110 // Idx of the STS module for each FEB, [ NbDpb ][ NbCrobPerDpb ][ NbFebsPerCrob ], -1 if inactive
111 std::vector<std::vector<std::vector<int32_t>>> viFebModuleIdx;
112
113 // Array to hold the active flag for all CROBs, [ NbDpb ][ NbCrobPerDpb ]
114 std::vector<std::vector<bool>> vbCrobActiveFlag;
115
116 //STS module side for each FEB, [ NbDpb ][ NbCrobPerDpb ][ NbFebsPerCrob ], 0 = P, 1 = N, -1 if inactive
117 std::vector<std::vector<std::vector<int32_t>>> viFebModuleSide;
118
119 // Total number of STS modules in the setup
120 const uint32_t uNbModules = fUnpackPar->GetNbOfModules();
121 LOG(info) << "Nr. of STS Modules: " << uNbModules;
122
123 //Initialize temporary "per Feb" fields
124 InitTempVectors(&viModuleType, &viModAddress, &viFebModuleIdx, &vbCrobActiveFlag, &viFebModuleSide);
125
126 // Total number of STS DPBs in system
127 const uint32_t uNbOfDpbs = fUnpackPar->GetNrOfDpbs();
128 LOG(info) << "Nr. of STS DPBs: " << uNbOfDpbs;
129
130 // Read dpb index map from parameter container
132
133 // Get Nr of Febs
135 LOG(info) << "Nr. of FEBs: " << fuNbFebs;
136
137 // Get Nr of Asics
138 const uint32_t uNbStsXyters = fUnpackPar->GetNrOfAsics();
139 LOG(info) << "Nr. of StsXyter ASICs: " << uNbStsXyters;
140
141 if (fvdTimeOffsetNsAsics.size() < uNbStsXyters) {
142 fvdTimeOffsetNsAsics.resize(uNbStsXyters, 0.0);
143 }
144
145 //Initialize class-wide "per Feb" fields
146 fviFebType.resize(uNbOfDpbs);
147
148 for (uint32_t uDpb = 0; uDpb < uNbOfDpbs; ++uDpb) {
149 fviFebType[uDpb].resize(fUnpackPar->GetNbCrobsPerDpb());
150 for (uint32_t uCrobIdx = 0; uCrobIdx < fUnpackPar->GetNbCrobsPerDpb(); ++uCrobIdx) {
151 fviFebType[uDpb][uCrobIdx].resize(fUnpackPar->GetNbFebsPerCrob(), -1);
152 for (uint32_t uFebIdx = 0; uFebIdx < fUnpackPar->GetNbFebsPerCrob(); ++uFebIdx) {
153 fvbFebPulser.push_back(fUnpackPar->IsFebPulser(uDpb, uCrobIdx, uFebIdx));
154 fvdFebAdcGain.push_back(fUnpackPar->GetFebAdcGain(uDpb, uCrobIdx, uFebIdx));
155 fvdFebAdcOffs.push_back(fUnpackPar->GetFebAdcOffset(uDpb, uCrobIdx, uFebIdx));
156
157 if (0 <= viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]
158 && static_cast<uint32_t>(viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]) < uNbModules
159 && 0 <= viFebModuleSide[uDpb][uCrobIdx][uFebIdx] && viFebModuleSide[uDpb][uCrobIdx][uFebIdx] < 2) {
160 switch (viModuleType[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]) {
161 case 0: // FEB-8-1 with ZIF connector on the right
162 {
163 // P side (0) has type A (0)
164 // N side (1) has type B (1)
165 fviFebType[uDpb][uCrobIdx][uFebIdx] = viFebModuleSide[uDpb][uCrobIdx][uFebIdx];
166
173 fviFebAddress.push_back(viModAddress[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]);
174 // + (viFebModuleSide[uDpb][uCrobIdx][uFebIdx] << 25));
175 fviFebSide.push_back(viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
176 break;
177 } // case 0: // FEB-8-1 with ZIF connector on the right
178 case 1: // FEB-8-1 with ZIF connector on the left
179 {
180 // P side (0) has type B (1)
181 // N side (1) has type A (0)
182 fviFebType[uDpb][uCrobIdx][uFebIdx] = !(viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
183
190 fviFebAddress.push_back(viModAddress[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]);
191 // + ((!viFebModuleSide[uDpb][uCrobIdx][uFebIdx]) << 25));
192 fviFebSide.push_back(viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
193 break;
194 } // case 1: // FEB-8-1 with ZIF connector on the left
195 default:
196 LOG(fatal) << Form("Bad module type for DPB #%02u CROB #%u FEB %02u: %d", uDpb, uCrobIdx, uFebIdx,
197 viModuleType[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]);
198 break;
199 }
200 } // FEB active and module index OK
201 else if (-1 == viFebModuleIdx[uDpb][uCrobIdx][uFebIdx] || -1 == viFebModuleSide[uDpb][uCrobIdx][uFebIdx]) {
202 fviFebAddress.push_back(0);
203 fviFebSide.push_back(-1);
204 } // Module index or type is set to inactive
205 else {
206 LOG(fatal) << Form("Bad module Index and/or Side for DPB #%02u CROB "
207 "#%u FEB %02u: %d %d",
208 uDpb, uCrobIdx, uFebIdx, viFebModuleIdx[uDpb][uCrobIdx][uFebIdx],
209 viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
210 } // Bad module index or type for this FEB
211 }
212 }
213 }
214
215 PrintActiveCrobs(vbCrobActiveFlag);
216 PrintAddressMaps(viFebModuleIdx, viFebModuleSide);
217
218 LOG(info) << "Unpacking data in bin sorter FW mode";
220
221 return true;
222}
223
224// -------------------------------------------------------------------------
226{
227 fDpbIdIndexMap.clear();
228 for (uint32_t uDpb = 0; uDpb < fUnpackPar->GetNrOfDpbs(); ++uDpb) {
229 fDpbIdIndexMap[fUnpackPar->GetDpbId(uDpb)] = uDpb;
230 LOG(info) << "Eq. ID for DPB #" << std::setw(2) << uDpb << " = 0x" << std::setw(4) << std::hex
231 << fUnpackPar->GetDpbId(uDpb) << std::dec << " => " << fDpbIdIndexMap[fUnpackPar->GetDpbId(uDpb)];
232 }
233}
234
235// -------------------------------------------------------------------------
236void CbmStsUnpackAlgoLegacy::InitTempVectors(std::vector<int32_t>* viModuleType, std::vector<int32_t>* viModAddress,
237 std::vector<std::vector<std::vector<int32_t>>>* viFebModuleIdx,
238 std::vector<std::vector<bool>>* vbCrobActiveFlag,
239 std::vector<std::vector<std::vector<int32_t>>>* viFebModuleSide)
240{
241 const uint32_t uNbModules = fUnpackPar->GetNbOfModules();
242 const uint32_t uNbOfDpbs = fUnpackPar->GetNrOfDpbs();
243
244 viModuleType->resize(uNbModules);
245 viModAddress->resize(uNbModules);
246 for (uint32_t uModIdx = 0; uModIdx < uNbModules; ++uModIdx) {
247 (*viModuleType)[uModIdx] = fUnpackPar->GetModuleType(uModIdx);
248 (*viModAddress)[uModIdx] = fUnpackPar->GetModuleAddress(uModIdx);
249 LOG(info) << "Module #" << std::setw(2) << uModIdx << " Type " << std::setw(4) << (*viModuleType)[uModIdx]
250 << " Address 0x" << std::setw(8) << std::hex << (*viModAddress)[uModIdx] << std::dec;
251 }
252 vbCrobActiveFlag->resize(uNbOfDpbs);
253 viFebModuleIdx->resize(uNbOfDpbs);
254 viFebModuleSide->resize(uNbOfDpbs);
255
256 for (uint32_t uDpb = 0; uDpb < uNbOfDpbs; ++uDpb) {
257 (*vbCrobActiveFlag)[uDpb].resize(fUnpackPar->GetNbCrobsPerDpb());
258 (*viFebModuleIdx)[uDpb].resize(fUnpackPar->GetNbCrobsPerDpb());
259 (*viFebModuleSide)[uDpb].resize(fUnpackPar->GetNbCrobsPerDpb());
260 for (uint32_t uCrobIdx = 0; uCrobIdx < fUnpackPar->GetNbCrobsPerDpb(); ++uCrobIdx) {
261 (*vbCrobActiveFlag)[uDpb][uCrobIdx] = fUnpackPar->IsCrobActive(uDpb, uCrobIdx);
262 (*viFebModuleIdx)[uDpb][uCrobIdx].resize(fUnpackPar->GetNbFebsPerCrob());
263 (*viFebModuleSide)[uDpb][uCrobIdx].resize(fUnpackPar->GetNbFebsPerCrob());
264 for (uint32_t uFebIdx = 0; uFebIdx < fUnpackPar->GetNbFebsPerCrob(); ++uFebIdx) {
265 (*viFebModuleIdx)[uDpb][uCrobIdx][uFebIdx] = fUnpackPar->GetFebModuleIdx(uDpb, uCrobIdx, uFebIdx);
266 (*viFebModuleSide)[uDpb][uCrobIdx][uFebIdx] = fUnpackPar->GetFebModuleSide(uDpb, uCrobIdx, uFebIdx);
267 }
268 }
269 }
270}
271
272// -------------------------------------------------------------------------
273void CbmStsUnpackAlgoLegacy::PrintActiveCrobs(const std::vector<std::vector<bool>>& vbCrobActiveFlag)
274{
275 for (uint32_t uDpb = 0; uDpb < fUnpackPar->GetNrOfDpbs(); ++uDpb) {
276 TString sPrintoutLine = Form("DPB #%02u CROB Active ?: ", uDpb);
277 for (uint32_t uCrobIdx = 0; uCrobIdx < fUnpackPar->GetNbCrobsPerDpb(); ++uCrobIdx) {
278 sPrintoutLine += Form("%1u", (vbCrobActiveFlag[uDpb][uCrobIdx] == true));
279 }
280 LOG(info) << sPrintoutLine;
281 }
282}
283
284// -------------------------------------------------------------------------
285void CbmStsUnpackAlgoLegacy::PrintAddressMaps(const std::vector<std::vector<std::vector<int32_t>>>& viFebModuleIdx,
286 const std::vector<std::vector<std::vector<int32_t>>>& viFebModuleSide)
287{
288 uint32_t uGlobalFebIdx = 0;
289 for (uint32_t uDpb = 0; uDpb < fUnpackPar->GetNrOfDpbs(); ++uDpb) {
290 for (uint32_t uCrobIdx = 0; uCrobIdx < fUnpackPar->GetNbCrobsPerDpb(); ++uCrobIdx) {
291 LOG(info) << Form("DPB #%02u CROB #%u: ", uDpb, uCrobIdx);
292 for (uint32_t uFebIdx = 0; uFebIdx < fUnpackPar->GetNbFebsPerCrob(); ++uFebIdx) {
293 if (0 <= viFebModuleIdx[uDpb][uCrobIdx][uFebIdx])
294 LOG(info) << Form(" FEB #%02u (%02u): Mod. Idx = %03d Side %c (%2d) Type %c "
295 "(%2d) (Addr. 0x%08x) ADC gain %4.0f e- ADC Offs %5.0f e-",
296 uFebIdx, uGlobalFebIdx, viFebModuleIdx[uDpb][uCrobIdx][uFebIdx],
297 1 == viFebModuleSide[uDpb][uCrobIdx][uFebIdx] ? 'N' : 'P',
298 viFebModuleSide[uDpb][uCrobIdx][uFebIdx],
299 1 == fviFebType[uDpb][uCrobIdx][uFebIdx] ? 'B' : 'A', fviFebType[uDpb][uCrobIdx][uFebIdx],
300 fviFebAddress[uGlobalFebIdx], fvdFebAdcGain[uGlobalFebIdx], fvdFebAdcOffs[uGlobalFebIdx]);
301 else
302 LOG(info) << Form("Disabled FEB #%02u (%02u): Mod. Idx = %03d Side %c (%2d) Type %c "
303 "(%2d) (Addr. 0x%08x) ADC gain %4.0f e- ADC Offs %5.0f e-",
304 uFebIdx, uGlobalFebIdx, viFebModuleIdx[uDpb][uCrobIdx][uFebIdx],
305 1 == viFebModuleSide[uDpb][uCrobIdx][uFebIdx] ? 'N' : 'P',
306 viFebModuleSide[uDpb][uCrobIdx][uFebIdx],
307 1 == fviFebType[uDpb][uCrobIdx][uFebIdx] ? 'B' : 'A', fviFebType[uDpb][uCrobIdx][uFebIdx],
308 fviFebAddress[uGlobalFebIdx], fvdFebAdcGain[uGlobalFebIdx], fvdFebAdcOffs[uGlobalFebIdx]);
309 uGlobalFebIdx++;
310 }
311 }
312 }
313}
314
315// -------------------------------------------------------------------------
317{
318 const uint32_t uNbOfDpbs = fUnpackPar->GetNrOfDpbs();
319 const uint32_t uNbStsXyters = fUnpackPar->GetNrOfAsics();
320
321 fvulCurrentTsMsb.resize(uNbOfDpbs);
322 fvuCurrentTsMsbCycle.resize(uNbOfDpbs);
323 for (uint32_t uDpb = 0; uDpb < uNbOfDpbs; ++uDpb) {
324 fvulCurrentTsMsb[uDpb] = 0;
325 fvuCurrentTsMsbCycle[uDpb] = 0;
326 }
327
328 fvvusLastTsChan.resize(uNbStsXyters);
329 fvvusLastAdcChan.resize(uNbStsXyters);
330 fvvuLastTsMsbChan.resize(uNbStsXyters);
331 fvvusLastTsMsbCycleChan.resize(uNbStsXyters);
332 for (uint32_t uAsicIdx = 0; uAsicIdx < uNbStsXyters; ++uAsicIdx) {
333 fvvusLastTsChan[uAsicIdx].resize(fUnpackPar->GetNbChanPerAsic(), 0);
334 fvvusLastAdcChan[uAsicIdx].resize(fUnpackPar->GetNbChanPerAsic(), 0);
335 fvvuLastTsMsbChan[uAsicIdx].resize(fUnpackPar->GetNbChanPerAsic(), 0);
337 }
338}
339
340void CbmStsUnpackAlgoLegacy::AddHitsToDigiVect(std::vector<stsxyter::FinalHit>* vmHitsIn,
341 std::vector<CbmStsDigi>* vDigiVectOut)
342{
343 for (auto itHitIn = vmHitsIn->begin(); itHitIn < vmHitsIn->end(); ++itHitIn) {
344 const uint32_t uAsicIdx = itHitIn->GetAsic();
345 const uint32_t uFebIdx = itHitIn->GetAsic() / fUnpackPar->GetNbAsicsPerFeb();
346 uint32_t uChanInMod =
347 itHitIn->GetChan() + fUnpackPar->GetNbChanPerAsic() * (itHitIn->GetAsic() % fUnpackPar->GetNbAsicsPerFeb());
351 if (0 == fviFebSide[uFebIdx])
352 uChanInMod = fUnpackPar->GetNbChanPerFeb() - uChanInMod - 1 // Invert channel order
353 + fUnpackPar->GetNbChanPerFeb(); // Offset for P (back) side
354
355 double dTimeInNs = itHitIn->GetTs() * stsxyter::kdClockCycleNs - fdTimeOffsetNs;
356 if (uAsicIdx < fvdTimeOffsetNsAsics.size()) dTimeInNs -= fvdTimeOffsetNsAsics[uAsicIdx];
357
358 const uint64_t ulTimeInNs = static_cast<uint64_t>(dTimeInNs);
359 const double dCalAdc = fvdFebAdcOffs[uFebIdx] + (itHitIn->GetAdc() - 1) * fvdFebAdcGain[uFebIdx];
360
361 if (0 == fviFebAddress[uFebIdx] || -1 == fviFebSide[uFebIdx]) {
362 LOG(error) << Form("Digi on disabled FEB %02u has address 0x%08x and side %d", uFebIdx, fviFebAddress[uFebIdx],
363 fviFebSide[uFebIdx]);
364 }
365
367 if (fvbFebPulser[uFebIdx]) {
368 if (fOptOutAVec) {
369 fOptOutAVec->emplace_back(fviFebAddress[uFebIdx], uChanInMod, ulTimeInNs, dCalAdc);
370 } // if (fOptOutAVec)
371 } // if (fvbFebPulser[uFebIdx])
372 else {
373 vDigiVectOut->emplace_back(fviFebAddress[uFebIdx], uChanInMod, ulTimeInNs, dCalAdc);
374 } // else of if (fvbFebPulser[uFebIdx])
375 }
376}
377
378bool CbmStsUnpackAlgoLegacy::unpack(const fles::Timeslice* ts, std::uint16_t uMsCompIdx, UInt_t uMsIdx)
379{
381 if (0 == fTsIndex) {
382 return true;
383 }
384
385 auto msDescriptor = ts->descriptor(uMsCompIdx, uMsIdx);
386
387 //Current equipment ID, tells from which DPB the current MS is originating
388 const uint32_t uCurrentEquipmentId = msDescriptor.eq_id;
389 const uint8_t* msContent = reinterpret_cast<const uint8_t*>(ts->content(uMsCompIdx, uMsIdx));
390 const uint32_t uSize = msDescriptor.size;
391
392 fulCurrentMsIdx = msDescriptor.idx;
393 LOG(debug) << "Microslice: " << fulCurrentMsIdx << " from EqId " << std::hex << uCurrentEquipmentId << std::dec
394 << " has size: " << uSize;
395
396 if (0 == fvbMaskedComponents.size()) fvbMaskedComponents.resize(ts->num_components(), false);
397
398 //Temp holder until current equipment ID is properly filled in MS
399 const uint32_t uCurrDpbId = static_cast<uint32_t>(uCurrentEquipmentId & 0xFFFF);
400
401 if (fMonitor && fMonitor->GetDebugMode()) {
402 const double dMsTime = (1e-9) * static_cast<double>(fulCurrentMsIdx);
403 if (uMsCompIdx < fMonitor->GetMaxNbFlibLinks()) {
404 if (fdStartTimeMsSz < 0) fdStartTimeMsSz = dMsTime;
405 fMonitor->FillMsSize(uMsCompIdx, uSize);
406 fMonitor->FillMsSizeTime(uMsCompIdx, dMsTime - fdStartTimeMsSz, uSize);
407 }
408 }
409
411 auto it = fDpbIdIndexMap.find(uCurrDpbId);
412 if (it == fDpbIdIndexMap.end()) {
413 if (false == fvbMaskedComponents[uMsCompIdx]) {
414 LOG(info) << "---------------------------------------------------------------";
415 //LOG(info) << FormatMsHeaderPrintout(msDescriptor);
416 LOG(warning) << "Could not find the sDPB index for AFCK id 0x" << std::hex << uCurrDpbId << std::dec
417 << " in timeslice " << fTsIndex << " in microslice " << uMsIdx << " component " << uMsCompIdx << "\n"
418 << "If valid this index has to be added in the STS "
419 "parameter file in the DbpIdArray field";
420 fvbMaskedComponents[uMsCompIdx] = true;
421
424 if (1 == fTsIndex) return true;
425 }
426 else
427 return true;
428
429 return false;
430 }
431 else
432 fuCurrDpbIdx = fDpbIdIndexMap[uCurrDpbId];
433
434 if (fMonitor) fMonitor->FillMsCntEvo(fulCurrentMsIdx);
435
436 // Check the current TS_MSb cycle and correct it if wrong
437 RefreshTsMsbFields(uMsIdx);
438
439 //Reset internal monitor variables for debugging info
440 if (fMonitor && fMonitor->GetDebugMode()) {
441 fMonitor->ResetDebugInfo();
442 }
443
444 //Main processing of MS content
445 LoopMsMessages(msContent, uSize, uMsIdx);
446
447 //Output debugging info
448 if (fMonitor) {
449 if (fMonitor->GetDebugMode()) {
450 fMonitor->PrintDebugInfo(fulCurrentMsIdx, fTsIndex, msDescriptor.flags, uSize);
451 }
452 for (auto itHit = fOutputVec.begin(); itHit != fOutputVec.end(); ++itHit) {
453 fMonitor->FillDigisTimeInRun(itHit->GetTime()); //check whether this does what it should
454 }
455 fMonitor->FillVectorSize(ts->index(), fOutputVec.size()); //check whether this does what it should
456 //fMonitor->DrawCanvases();
457 }
458
459 AddHitsToDigiVect(&fvmHitsInMs, &fOutputVec);
460
462 fvmHitsInMs.clear();
463
464 return true;
465}
466
467// -------------------------------------------------------------------------
469{
470 uint32_t uTsMsbCycleHeader;
471 if (fbUseFwBinning) {
473 }
474 else {
475 uTsMsbCycleHeader = std::floor(fulCurrentMsIdx / (stsxyter::kulTsCycleNbBins * stsxyter::kdClockCycleNs));
476 }
477
478 if (0 == uMsIdx) {
479 if (uTsMsbCycleHeader != fvuCurrentTsMsbCycle[fuCurrDpbIdx])
480 LOG(info) << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << fulCurrentMsIdx << " MS Idx "
481 << std::setw(4) << uMsIdx << " Msg Idx " << std::setw(5) << 0 << " DPB " << std::setw(2) << fuCurrDpbIdx
482 << " Old TsMsb " << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy " << std::setw(5)
483 << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " New MsbCy " << uTsMsbCycleHeader;
484 fvuCurrentTsMsbCycle[fuCurrDpbIdx] = uTsMsbCycleHeader;
486 }
487 else if (uTsMsbCycleHeader != fvuCurrentTsMsbCycle[fuCurrDpbIdx]) {
488 if (4194303 == fvulCurrentTsMsb[fuCurrDpbIdx]) {
489 LOG(info) << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << fulCurrentMsIdx << " MS Idx "
490 << std::setw(4) << uMsIdx << " Msg Idx " << std::setw(5) << 0 << " DPB " << std::setw(2) << fuCurrDpbIdx
491 << " Old TsMsb " << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy " << std::setw(5)
492 << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " New MsbCy " << uTsMsbCycleHeader;
493 }
494 else {
495 LOG(warning) << "TS MSB cycle from MS header does not match current cycle from data "
496 << "for TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << fulCurrentMsIdx << " MsInTs "
497 << std::setw(3) << uMsIdx << " ====> " << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " (cnt) VS "
498 << uTsMsbCycleHeader << " (header)";
499 }
500 fvuCurrentTsMsbCycle[fuCurrDpbIdx] = uTsMsbCycleHeader;
501 }
502}
503
504// -------------------------------------------------------------------------
505void CbmStsUnpackAlgoLegacy::LoopMsMessages(const uint8_t* msContent, const uint32_t uSize, const size_t uMsIdx)
506{
507 // If not integer number of message in input buffer, print warning/error
508 if (0 != (uSize % sizeof(stsxyter::Message))) {
509 LOG(error) << "The input microslice buffer does NOT "
510 << "contain only complete sDPB messages!";
511 }
512 // Compute the number of complete messages in the input microslice buffer
513 const uint32_t uNbMessages = (uSize - (uSize % sizeof(stsxyter::Message))) / sizeof(stsxyter::Message);
514
515 // Prepare variables for the loop on contents
516 const stsxyter::Message* pMess = reinterpret_cast<const stsxyter::Message*>(msContent);
517
518 for (uint32_t uIdx = 0; uIdx < uNbMessages; uIdx++) {
520 const stsxyter::MessType typeMess = pMess[uIdx].GetMessType();
521
522 if (fMonitor && fMonitor->GetDebugMode()) {
523 fMonitor->ProcessDebugInfo(pMess[uIdx], fuCurrDpbIdx);
524 }
525 switch (typeMess) {
527 ProcessHitInfo(pMess[uIdx]);
528 break;
529 }
531 ProcessTsMsbInfo(pMess[uIdx], uIdx, uMsIdx);
532 break;
533 }
535 ProcessEpochInfo(pMess[uIdx]);
536 if (0 < uIdx) {
537 LOG(info) << "CbmStsUnpackAlgoLegacy::DoUnpack => "
538 << "EPOCH message at unexpected position in MS: message " << uIdx << " VS message 0 expected!";
539 }
540 break;
541 }
543 ProcessStatusInfo(pMess[uIdx], uIdx);
544 break;
545 }
547 break;
548 }
550 ProcessErrorInfo(pMess[uIdx]);
551 break;
552 }
554 break;
555 }
556 default: {
557 LOG(fatal) << "CbmStsUnpackAlgoLegacy::DoUnpack => "
558 << "Unknown message type, should never happen, stopping "
559 "here! Type found was: "
560 << static_cast<int>(typeMess);
561 }
562 }
563 }
564}
565
566// -------------------------------------------------------------------------
568{
569 uint16_t usElinkIdx;
570 if (fbUseFwBinning) {
571 usElinkIdx = mess.GetLinkIndexHitBinning();
572 }
573 else {
574 usElinkIdx = mess.GetLinkIndex();
575 }
576 const uint32_t uCrobIdx = usElinkIdx / fUnpackPar->GetNbElinkPerCrob();
577 const int32_t uFebIdx = fUnpackPar->ElinkIdxToFebIdx(usElinkIdx);
578 if (-1 == uFebIdx) {
579 LOG(warning) << "CbmStsUnpackAlgoLegacy::ProcessHitInfo => "
580 << "Wrong elink Idx! Elink raw " << Form("%d remap %d", usElinkIdx, uFebIdx);
581 return;
582 }
583 const uint32_t uAsicIdx =
585 + fUnpackPar->ElinkIdxToAsicIdx(1 == fviFebType[fuCurrDpbIdx][uCrobIdx][uFebIdx], usElinkIdx);
586 //LOG(info) << "Test " << uFebIdx << " " << uAsicIdx / fUnpackPar->GetNbAsicsPerFeb();
587 //const uint32_t uFebIdx = uAsicIdx / fUnpackPar->GetNbAsicsPerFeb(); // delete this?
588
589 const uint16_t usChan = mess.GetHitChannel();
590 const uint16_t usRawAdc = mess.GetHitAdc();
591 uint16_t usRawTs;
592 if (fbUseFwBinning) {
593 usRawTs = mess.GetHitTimeBinning();
594 }
595 else {
596 usRawTs = mess.GetHitTimeFull();
597 }
598 const uint32_t uChanInFeb = usChan + fUnpackPar->GetNbChanPerAsic() * (uAsicIdx % fUnpackPar->GetNbAsicsPerFeb());
599
602 if (usRawTs == fvvusLastTsChan[uAsicIdx][usChan]
603 && (fbDupliWithoutAdc || usRawAdc == fvvusLastAdcChan[uAsicIdx][usChan])
607 LOG(debug) << "CbmStsUnpackAlgoLegacy::ProcessHitInfo => "
608 << Form("Rejecting duplicate on Asic %3u channel %3u, TS %3u, MSB %lu, Cycle %u, ADC %2u", uAsicIdx,
609 usChan, usRawTs, fvulCurrentTsMsb[fuCurrDpbIdx], fvuCurrentTsMsbCycle[fuCurrDpbIdx], usRawAdc);
610 return;
611 } // if SMX 2.0 DPB and same TS, ADC, TS MSB, TS MSB cycle!
612 } // if (fbRejectDuplicateDigis)
613 fvvusLastTsChan[uAsicIdx][usChan] = usRawTs;
614 fvvusLastAdcChan[uAsicIdx][usChan] = usRawAdc;
617
618 // Compute the Full time stamp
619 const uint64_t ulHitTime = GetFullTimeStamp(usRawTs);
620
622 if (0 != fviFebAddress[uFebIdx] && fdAdcCut < usRawAdc) {
625 if (false == fbUseChannelMask || false == fvvbMaskedChannels[uFebIdx][uChanInFeb])
626 fvmHitsInMs.push_back(stsxyter::FinalHit(ulHitTime, usRawAdc, uAsicIdx, usChan, fuCurrDpbIdx, uCrobIdx));
627 }
628
629 // Convert the Hit time in bins to Hit time in ns
630 const double dHitTimeNs = ulHitTime * stsxyter::kdClockCycleNs;
631
633 if (mess.IsHitMissedEvts() && fOptOutBVec != nullptr)
634 fOptOutBVec->push_back(
635 CbmErrorMessage(ECbmModuleId::kSts, dHitTimeNs, uAsicIdx, 1 << stsxyter::kusLenStatStatus, usChan));
636
637 if (fMonitor) {
638 // Check Starting point of histos with time as X axis
639 if (-1 == fdStartTime) {
640 fdStartTime = dHitTimeNs;
641 }
642 if (fMonitor->GetDebugMode()) {
643 fMonitor->FillHitDebugMonitoringHistos(uAsicIdx, usChan, usRawAdc, usRawTs, mess.IsHitMissedEvts());
644 }
645 const uint32_t uAsicInFeb = uAsicIdx % fUnpackPar->GetNbAsicsPerFeb();
646 const double dTimeSinceStartSec = (dHitTimeNs - fdStartTime) * 1e-9;
647 const double dCalAdc = fvdFebAdcOffs[uFebIdx] + (usRawAdc - 1) * fvdFebAdcGain[uFebIdx];
648 fMonitor->FillHitMonitoringHistos(uFebIdx, usChan, uChanInFeb, usRawAdc, dCalAdc, usRawTs, mess.IsHitMissedEvts());
649 fMonitor->FillHitEvoMonitoringHistos(uFebIdx, uAsicIdx, uAsicInFeb, uChanInFeb, dTimeSinceStartSec,
650 mess.IsHitMissedEvts());
651 }
652}
653
654
655void CbmStsUnpackAlgoLegacy::ProcessTsMsbInfo(const stsxyter::Message& mess, uint32_t uMessIdx, uint32_t uMsIdx)
656{
657 uint32_t uVal;
658 if (fbUseFwBinning) {
659 uVal = mess.GetTsMsbValBinning();
660 }
661 else {
662 uVal = mess.GetTsMsbVal();
663 }
664
665 // Update Status counters
666 if (uVal < fvulCurrentTsMsb[fuCurrDpbIdx]) {
667
668 LOG(info) << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << fulCurrentMsIdx << " MS Idx "
669 << std::setw(4) << uMsIdx << " Msg Idx " << std::setw(5) << uMessIdx << " DPB " << std::setw(2)
670 << fuCurrDpbIdx << " Old TsMsb " << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy "
671 << std::setw(5) << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " new TsMsb " << std::setw(5) << uVal;
672
674 }
675 if (
676 uVal != fvulCurrentTsMsb[fuCurrDpbIdx] + 1 && !(0 == uVal && 4194303 == fvulCurrentTsMsb[fuCurrDpbIdx])
677 &&
678 1 != uMessIdx &&
679 !(0 == uVal && 0 == fvulCurrentTsMsb[fuCurrDpbIdx] && 2 == uMessIdx) &&
680 !(uVal == fvulCurrentTsMsb[fuCurrDpbIdx] && 2 == uMessIdx)
681 &&
682 uVal < fvulCurrentTsMsb
683 [fuCurrDpbIdx]
684 ) {
685 LOG(info) << "TS MSb Jump in "
686 << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << fulCurrentMsIdx << " MS Idx "
687 << std::setw(4) << uMsIdx << " Msg Idx " << std::setw(5) << uMessIdx << " DPB " << std::setw(2)
688 << fuCurrDpbIdx << " => Old TsMsb " << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " new TsMsb "
689 << std::setw(5) << uVal;
690 }
691
694 if (4194303 == uVal && 1 == uMessIdx)
696 else
698
699 if (fMonitor && fMonitor->GetDebugMode()) { //also if( 1 < uMessIdx )?
700 fMonitor->FillStsDpbRawTsMsb(fuCurrDpbIdx, fvulCurrentTsMsb[fuCurrDpbIdx]);
701 fMonitor->FillStsDpbRawTsMsbSx(fuCurrDpbIdx, fvulCurrentTsMsb[fuCurrDpbIdx]);
702 fMonitor->FillStsDpbRawTsMsbDpb(fuCurrDpbIdx, fvulCurrentTsMsb[fuCurrDpbIdx]);
703 }
704}
705
707{
708 // Currently not used
709 // uint32_t uVal = mess.GetEpochVal();
710 // uint32_t uCurrentCycle = uVal % stsxyter::kulTsCycleNbBins;
711}
712
713// -------------------------------------------------------------------------
715{
716 if (fMonitor && fMonitor->GetDebugMode()) {
717 std::cout << Form("DPB %2u TS %12lu MS %12lu mess %5u ", fuCurrDpbIdx, fTsIndex, fulCurrentMsIdx, uIdx);
719 }
720
721 const uint16_t usElinkIdx = mess.GetStatusLink();
722 const uint32_t uCrobIdx = usElinkIdx / fUnpackPar->GetNbElinkPerCrob();
723 const int32_t uFebIdx = fUnpackPar->ElinkIdxToFebIdx(usElinkIdx);
724 if (-1 == uFebIdx) {
725 LOG(warning) << "CbmStsUnpackAlgoLegacy::DoUnpack => "
726 << "Wrong elink Idx! Elink raw " << Form("%d remap %d", usElinkIdx, uFebIdx);
727 return;
728 }
729 const uint32_t uAsicIdx =
731 + fUnpackPar->ElinkIdxToAsicIdx(1 == fviFebType[fuCurrDpbIdx][uCrobIdx][uFebIdx], usElinkIdx);
732
733 if (fMonitor) {
734 const uint16_t usStatusField = mess.GetStatusStatus();
735 fMonitor->FillStsStatusMessType(uAsicIdx, usStatusField);
736 }
738 const int64_t ulTime = GetFullTimeStamp(0);
739
741 const double dTimeNs = ulTime * stsxyter::kdClockCycleNs;
742 if (fOptOutBVec) {
743 fOptOutBVec->push_back(
744 CbmErrorMessage(ECbmModuleId::kSts, dTimeNs, uAsicIdx, mess.GetStatusStatus(), mess.GetData()));
745 }
746}
747
748// -------------------------------------------------------------------------
749uint64_t CbmStsUnpackAlgoLegacy::GetFullTimeStamp(const uint16_t usRawTs)
750{
751 // Use TS w/o overlap bits as they will anyway come from the TS_MSB
752
753 uint64_t ulTime;
754 if (fbUseFwBinning) {
755 ulTime =
756 usRawTs
757 + static_cast<uint64_t>(stsxyter::kuHitNbTsBinsBinning) * static_cast<uint64_t>(fvulCurrentTsMsb[fuCurrDpbIdx])
758 + static_cast<uint64_t>(stsxyter::kulTsCycleNbBinsBinning)
759 * static_cast<uint64_t>(fvuCurrentTsMsbCycle[fuCurrDpbIdx]);
760 }
761 else {
762 ulTime =
763 usRawTs
764 + static_cast<uint64_t>(stsxyter::kuHitNbTsBins) * (static_cast<uint64_t>(fvulCurrentTsMsb[fuCurrDpbIdx]) % 4);
765 }
766 return ulTime;
767}
768
769// -------------------------------------------------------------------------
771{
772 if (mess.IsMsErrorFlagOn()) {
773 if (fMonitor) {
774 fMonitor->FillMsErrorsEvo(fulCurrentMsIdx, mess.GetMsErrorType());
775 }
776 if (fOptOutBVec) {
777 fOptOutBVec->push_back(
779 }
780 }
781}
782
783// -------------------------------------------------------------------------
784void CbmStsUnpackAlgoLegacy::MaskNoisyChannel(const uint32_t uFeb, const uint32_t uChan, const bool bMasked)
785{
786 if (false == fbUseChannelMask) {
787 fbUseChannelMask = true;
789 for (uint32_t uFebIdx = 0; uFebIdx < fuNbFebs; ++uFebIdx) {
790 fvvbMaskedChannels[uFebIdx].resize(fUnpackPar->GetNbChanPerFeb(), false);
791 }
792 }
793 if (uFeb < fuNbFebs && uChan < fUnpackPar->GetNbChanPerFeb())
794 fvvbMaskedChannels[uFeb][uChan] = bMasked;
795 else
796 LOG(fatal) << "CbmStsUnpackAlgoLegacy::MaskNoisyChannel => Invalid FEB "
797 "and/or CHAN index:"
798 << Form(" %u vs %u and %u vs %u", uFeb, fuNbFebs, uChan, fUnpackPar->GetNbChanPerFeb());
799}
800// -------------------------------------------------------------------------
@ kSts
Silicon Tracking System.
CbmRoot (+externals) headers.
Double_t GetFebAdcGain(UInt_t uDpbIdx, UInt_t uCrobIdx, UInt_t uFebIdx)
UInt_t GetDpbId(UInt_t uDpbIdx)
Int_t ElinkIdxToFebIdx(UInt_t uElink)
Int_t GetFebModuleIdx(UInt_t uDpbIdx, UInt_t uCrobIdx, UInt_t uFebIdx)
UInt_t GetModuleType(UInt_t uModuleIdx)
static constexpr UInt_t GetNbFebsPerCrob()
static constexpr UInt_t GetNbAsicsPerFeb()
static constexpr UInt_t GetNbElinkPerCrob()
Double_t GetFebAdcOffset(UInt_t uDpbIdx, UInt_t uCrobIdx, UInt_t uFebIdx)
static constexpr UInt_t GetNbAsicsPerCrob()
Bool_t IsCrobActive(UInt_t uDpbIdx, UInt_t uCrobIdx)
static constexpr UInt_t GetNbCrobsPerDpb()
UInt_t GetModuleAddress(UInt_t uModuleIdx)
UInt_t ElinkIdxToAsicIdx(Bool_t bFebType, UInt_t uElink)
Bool_t IsFebPulser(UInt_t uFebInSystIdx)
Int_t GetFebModuleSide(UInt_t uDpbIdx, UInt_t uCrobIdx, UInt_t uFebIdx)
static constexpr UInt_t GetNbChanPerAsic()
static constexpr UInt_t GetNbChanPerFeb()
std::vector< double > fvdTimeOffsetNsAsics
Time offsets per Asic???
bool fbUseFwBinning
Enables firmware binning (some implementations ignore this)
uint32_t fdAdcCut
Minimum adc cut to store a hit.
bool fbRejectDuplicateDigis
Enables the rejection of duplicate digis.
std::shared_ptr< CbmStsUnpackMonitor > fMonitor
Potential (online) monitor for the unpacking process.
bool fbDupliWithoutAdc
If rejecting duplicate digis, enables rejection even if ADC differs.
uint64_t GetFullTimeStamp(const uint16_t usRawTs)
Get full time stamp from raw time stamp.
std::vector< double > fvdFebAdcGain
Module side for each FEB, [ NbDpb * NbCrobPerDpb * NbFebsPerCrob ].
void PrintAddressMaps(const std::vector< std::vector< std::vector< int32_t > > > &viFebModuleIdx, const std::vector< std::vector< std::vector< int32_t > > > &viFebModuleSide)
void ProcessEpochInfo(const stsxyter::Message &mess)
void ProcessErrorInfo(const stsxyter::Message &mess)
void InitTempVectors(std::vector< int32_t > *viModuleType, std::vector< int32_t > *viModAddress, std::vector< std::vector< std::vector< int32_t > > > *viFebModuleIdx, std::vector< std::vector< bool > > *vbCrobActiveFlag, std::vector< std::vector< std::vector< int32_t > > > *viFebModuleSide)
std::vector< uint64_t > fvulCurrentTsMsb
std::map< uint32_t, uint32_t > fDpbIdIndexMap
Number of FEBs with StsXyter ASICs.
std::vector< stsxyter::FinalHit > fvmHitsInMs
Hits time-sorting.
CbmMcbm2018StsPar * fUnpackPar
Settings from parameter file.
bool initParSet(FairParGenericSet *parset)
ADC offset in e-, [ NbDpb * NbCrobPerDpb * NbFebsPerCrob ].
void InitDpbIdIndexMap()
Map of DPB Identifier to DPB index.
std::vector< bool > fvbMaskedComponents
Control flags.
std::vector< std::vector< uint16_t > > fvvusLastTsChan
std::vector< std::vector< bool > > fvvbMaskedChannels
uint32_t fuCurrDpbIdx
Current data properties.
void RefreshTsMsbFields(const size_t uMsIdx)
std::vector< int32_t > fviFebSide
STS address for each FEB, [ NbDpb * NbCrobPerDpb * NbFebsPerCrob ].
virtual void MaskNoisyChannel(const uint32_t uFeb, const uint32_t uChan, const bool bMasked=true)
Mask a Noisy Channel.
void PrintActiveCrobs(const std::vector< std::vector< bool > > &vbCrobActiveFlag)
void ProcessStatusInfo(const stsxyter::Message &mess, uint32_t uIdx)
void ProcessHitInfo(const stsxyter::Message &mess)
TS MSB cycle of last hit message for each channel, [ AsicIdx ][ Chan ].
bool unpack(const fles::Timeslice *ts, std::uint16_t icomp, UInt_t imslice)
Unpack a given microslice. To be implemented in the derived unpacker algos.
std::vector< std::vector< std::vector< int32_t > > > fviFebType
std::vector< std::vector< uint32_t > > fvvuLastTsMsbChan
ADC of last hit message for each channel, [ AsicIdx ][ Chan ].
void ProcessTsMsbInfo(const stsxyter::Message &mess, uint32_t uMessIdx=0, uint32_t uMsIdx=0)
void AddHitsToDigiVect(std::vector< stsxyter::FinalHit > *vmHitsIn, std::vector< CbmStsDigi > *vDigiVectOut)
Add the hits to the output buffer as Digis.
void LoopMsMessages(const uint8_t *msContent, const uint32_t uSize, const size_t uMsIdx)
uint64_t fulCurrentMsIdx
Vector of channel masks, [ NbFeb ][ NbCHanInFeb ], used only if fbUseChannelMask is true.
std::vector< double > fvdFebAdcOffs
ADC gain in e-/b, [ NbDpb * NbCrobPerDpb * NbFebsPerCrob ].
double fdTimeOffsetNs
User settings: Data correction parameters.
std::vector< uint32_t > fvuCurrentTsMsbCycle
Current TS MSB for each DPB.
std::vector< std::vector< uint16_t > > fvvusLastTsMsbCycleChan
TS MSB of last hit message for each channel, [ AsicIdx ][ Chan ].
std::vector< int32_t > fviFebAddress
Pulser flag for each FEB, [ NbDpb * NbCrobPerDpb * NbFebsPerCrob ].
std::vector< std::vector< uint16_t > > fvvusLastAdcChan
TS of last hit message for each channel, [ AsicIdx ][ Chan ].
std::vector< bool > fvbFebPulser
FEB type, [ NbDpb ][ NbCrobPerDpb ][ NbFebsPerCrob ], 0 = A, 1 = B, -1 if inactive.
static const uint32_t kuMaxTsMsbDiffDuplicates
All hits (time in bins, ADC in bins, asic, channel) in last MS, sorted with "<" operator.
XPU_D bool IsHitMissedEvts() const
For Hit data: Returns Missed event flag (1 bit field)
XPU_D uint32_t GetTsMsbValBinning() const
For TS MSB data: Returns the TS MSB 29 bit field)
XPU_D uint16_t GetHitAdc() const
For Hit data: Returns ADC value (5 bit field)
XPU_D uint16_t GetHitChannel() const
For Hit data: Returns StsXYTER channel number (7 bit field)
bool PrintMess(std::ostream &os, MessagePrintMask ctrl=MessagePrintMask::msg_print_Human, bool bBinning=true) const
XPU_D uint16_t GetLinkIndex() const
For all data: Returns the (global) index of the eLink on which the message was received (n bit field)
XPU_D uint16_t GetStatusStatus() const
For Status data: Returns the Status field from ACK frame (4 bit field)
XPU_D MessType GetMessType() const
Returns the message type, see enum MessType.
XPU_D uint16_t GetLinkIndexHitBinning() const
XPU_D uint32_t GetData() const
XPU_D uint32_t GetTsMsbVal() const
For TS MSB data: Returns the TS MSB 22 bit field)
XPU_D uint16_t GetHitTimeFull() const
For Hit data: Returns Full timestamp (10 bit field including 2 bits overlap)
XPU_D uint16_t GetHitTimeBinning() const
XPU_D uint16_t GetStatusLink() const
For Status data: Returns the Link Inedx (9 bit field)
XPU_D uint16_t GetMsErrorType() const
For End of MS data: Returns the MS error type field (2 bit field)
XPU_D bool IsMsErrorFlagOn() const
For End of MS data: Returns the MS error flag (1 bit field)
Hash for CbmL1LinkKey.
static constexpr uint32_t kuHitNbTsBinsBinning
static constexpr uint64_t kulTsCycleNbBins
static constexpr uint64_t kulTsCycleNbBinsBinning
static constexpr uint32_t kuHitNbTsBins
static constexpr double kdClockCycleNs
MessType
Message types.
static constexpr uint16_t kusLenStatStatus