CbmRoot
Loading...
Searching...
No Matches
CbmMcbm2018UnpackerAlgoTrdR.cxx
Go to the documentation of this file.
1/* Copyright (C) 2020-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Florian Uhlig [committer] */
4
6
7#include "CbmTrdAddress.h"
9#include "CbmTrdParModDigi.h"
10#include "CbmTrdParSpadic.h"
11
12#include <Logger.h>
13
14#include "TH2I.h"
15#include "TObjString.h"
16#include "TProfile.h"
17#include "TSystem.h"
18#include "TVector3.h"
19
20#include <iostream>
21#include <map>
22
25 //, fRawToDigi( new CbmTrdRawToDigiR )
26 , fdMsSizeInCC(0)
27 , fbMonitorMode(kFALSE)
28 , fbDebugMonitorMode(kFALSE)
29 , fbWriteOutput(kTRUE)
30 , fbDebugWriteOutput(kFALSE)
31 , fbBaselineAvg(kFALSE)
32 , fTrdDigiVector(nullptr)
33 , fTrdRawMessageVector(nullptr)
34 , fSpadicInfoMsgVector(nullptr)
35 //, fHistoMap()
36 , fIsActiveHistoVec(ECbmTrdUnpackerHistograms::kEndDefinedHistos, false)
37 , fHistoArray()
38 , fLastDigiTimeVec()
39 , fNbTimeslices(0)
40 , fCurrTsIdx(0)
41 , fMsIndex(0)
42 , fTsStartTime(0.0)
43 , fTsStopTimeCore(0.0)
44 , fMsTime(0.0)
45 , fSpadicEpoch(0)
46 , fLastFulltime(0)
47 , fNbSpadicRawMsg(0)
48 , fNbWildRda(0)
49 , fNbSpadicErrorMsg(0)
50 , fNbUnkownWord(0)
51 , fNbSpadicEpochMsg(0)
52 , fParContList(nullptr)
53 , fRefGeoTag("trd_v20a_mcbm")
54 , fAsicPar(nullptr)
55 , fDigiPar(nullptr)
56 , fGasPar(nullptr)
57 , fGainPar(nullptr)
58 , fSpadicMap()
59 , fAsicChannelMap()
60 , fIsFirstChannelsElinkEven(false)
61{
62}
63
65{
66 if (fTrdRawMessageVector != nullptr) { delete fTrdRawMessageVector; }
67 if (nullptr != fParCList) delete fParCList;
68 if (nullptr != fParContList) delete fParContList;
69
70 if (nullptr != fAsicPar) delete fAsicPar;
71 if (nullptr != fDigiPar) delete fDigiPar;
72 if (nullptr != fGasPar) delete fGasPar;
73 if (nullptr != fGainPar) delete fGainPar;
74}
75
77{
78 LOG(debug) << "Initializing CbmMcbm2018UnpackerAlgoTrdR";
79 //fRawToDigi->Init();
80 fbIgnoreOverlapMs = kTRUE;
81 // fdMsSizeInNs = 1.28e6; //FIXME time should come from parameter file
83
84 return kTRUE;
85}
86
92
94{
95 LOG(info) << "Finish of CbmMcbm2018UnpackerAlgoTrdR. Unpacked \n " << fNbTimeslices << " Timeslices with \n "
96 << fNbSpadicRawMsg << " Spadic Raw Messages,\n " << fNbSpadicEpochMsg << " Spadic Epoch Messages,\n "
97 << fNbSpadicErrorMsg << " Spadic Info Messages,\n " << fNbWildRda << " Unexpected RDA Words and\n "
98 << fNbUnkownWord << " Unknown Words.";
99}
100
101// ---- InitContainers ----------------------------------------------------
103{
104 LOG(debug) << "Initializing Containers of CbmMcbm2018UnpackerAlgoTrdR";
105
106 Bool_t initOK = ReInitContainers();
107
108 return initOK;
109}
110
111// ---- ReInitContainers ----------------------------------------------------
113{
114 LOG(debug) << "(Re-)Initializing Containers of CbmMcbm2018UnpackerAlgoTrdR";
115
116 Bool_t initOk = kTRUE;
117
118 if (!(fAsicPar = (CbmTrdParSetAsic*) fParContList->FindObject("CbmTrdParSetAsic"))) {
119 LOG(warning) << "CbmTrdParSetAsic not found";
120 initOk = kFALSE;
121 }
122 if (!(fDigiPar = (CbmTrdParSetDigi*) fParContList->FindObject("CbmTrdParSetDigi"))) {
123 LOG(warning) << "CbmTrdParSetDigi not found";
124 initOk = kFALSE;
125 }
126 if (!(fGasPar = (CbmTrdParSetGas*) fParContList->FindObject("CbmTrdParSetGas"))) {
127 LOG(warning) << "CbmTrdParSetGas not found";
128 initOk = kFALSE;
129 }
130 if (!(fGainPar = (CbmTrdParSetGain*) fParContList->FindObject("CbmTrdParSetGain"))) {
131 LOG(warning) << "CbmTrdParSetGain not found";
132 initOk = kFALSE;
133 }
134
135 if (initOk) initOk = InitParameters();
136
137 return initOk;
138}
139
140// ---- GetParList ----------------------------------------------------
142{
143 if (fParContList) { return fParContList; }
144 else // create list with default parameters for trd
145 {
146 fParContList = new TList();
147
150 fGasPar = new CbmTrdParSetGas();
152
155 fParContList->Add(fGasPar);
157
158 return fParContList;
159 }
160}
161
162// ---- InitParameters ----------------------------------------------------
164{
165 Bool_t initOk = kTRUE;
166
167 // Initialize the spadic address map
168 CbmTrdHardwareSetupR hwSetup;
170 initOk &= !(fSpadicMap.empty()); // at least check that the loaded map is not empty
172 initOk &= !(fAsicChannelMap.empty()); // at least check that the loaded map is not empty
173 if (initOk)
174 LOG(debug) << "CbmMcbm2018UnpackerAlgoTrdR - Successfully initialized "
175 "Spadic hardware address map";
176 return initOk;
177}
178
179Bool_t CbmMcbm2018UnpackerAlgoTrdR::ProcessTs(const fles::Timeslice& ts)
180{
181 fCurrTsIdx = ts.index();
182 size_t itimeslice = fCurrTsIdx / 10;
183 auto timeshiftpair = fmapTimeshifts.find(itimeslice);
184 if (timeshiftpair != fmapTimeshifts.end()) { fvecTimeshiftsPar = &timeshiftpair->second; }
185
186 fTsStartTime = static_cast<Double_t>(ts.descriptor(0, 0).idx);
187
189 if (0 == fNbTimeslices) {
190 fuNbCoreMsPerTs = ts.num_core_microslices();
191 fuNbOverMsPerTs = ts.num_microslices(0) - ts.num_core_microslices();
194 LOG(info) << "CbmMcbm2018UnpackerAlgoTrdR::ProcessTs :";
195 LOG(info) << "Timeslice parameters: each TS has " << fuNbCoreMsPerTs << " Core MS and " << fuNbOverMsPerTs
196 << " Overlap MS, for a core duration of " << fdTsCoreSizeInNs << " ns and a full duration of "
197 << fdTsFullSizeInNs << " ns";
198
202 LOG(info) << "In each TS " << fuNbMsLoop << " MS will be looped over";
203 }
204
206 for (UInt_t MsIndex = 0; MsIndex < fuNbMsLoop; MsIndex++) {
208 for (UInt_t uMsCompIdx = 0; uMsCompIdx < fvMsComponentsList.size(); ++uMsCompIdx) {
209 UInt_t uMsComp = fvMsComponentsList[uMsCompIdx];
210
211 if (kFALSE == ProcessMs(ts, uMsComp, MsIndex)) {
214 std::sort(fTrdDigiVector->begin(), fTrdDigiVector->end(),
215 [](const CbmTrdDigi& a, const CbmTrdDigi& b) -> bool { return a.GetTime() < b.GetTime(); });
217 std::sort(fTrdRawMessageVector->begin(), fTrdRawMessageVector->end(),
218 [](const CbmTrdRawMessageSpadic& a, const CbmTrdRawMessageSpadic& b) -> bool {
219 return a.GetTime() < b.GetTime();
220 });
221 }
222
223 LOG(error) << "Failed to process ts " << fCurrTsIdx << " MS " << MsIndex << " for component " << uMsComp;
224 return kFALSE;
225 }
226 }
227 }
228
230 std::sort(fTrdDigiVector->begin(), fTrdDigiVector->end(),
231 [](const CbmTrdDigi& a, const CbmTrdDigi& b) -> bool { return a.GetTime() < b.GetTime(); });
232
234 return kTRUE;
235}
236
237Bool_t CbmMcbm2018UnpackerAlgoTrdR::ProcessMs(const fles::Timeslice& ts, size_t uMsCompIdx, size_t uMsIdx)
238{
239 fles::MicrosliceDescriptor msDesc = ts.descriptor(uMsCompIdx, uMsIdx);
240 // uint16_t msEquipmentID = msDesc.eq_id; ///< Equipment identifier. Specifies the FLES input link. #FU 27.03.20 unused
241 uint32_t msSize = msDesc.size;
242 // uint64_t msTime = msDesc.idx; ///< Start time of the microslice in ns since global time zero. #FU 27.03.20 unused
243 uint32_t msNbWords =
244 (msSize - (msSize % kBytesPerWord)) / kBytesPerWord;
245
246 const uint8_t* msPointer = reinterpret_cast<const uint8_t*>(ts.content(uMsCompIdx, uMsIdx));
247 const uint64_t* msContent = reinterpret_cast<const uint64_t*>(msPointer);
248
250 for (uint32_t iWord = 0; iWord < msNbWords; iWord++) {
251 uint64_t curWord = static_cast<uint64_t>(msContent[iWord]);
252 Spadic::MsMessageType wordType = GetMessageType(curWord);
253
254 if (wordType == Spadic::MsMessageType::kSOM) {
255 //LOG(info) << "New Spadic Message!" ; //debug
256 CbmTrdRawMessageSpadic raw = CreateRawMessage(curWord, msDesc);
257 uint8_t nSamples = raw.GetNrSamples();
259 if (nSamples > 3) {
260 uint8_t nRda = GetNumRda(nSamples);
261 uint8_t curSample = 3; // first 3 samples are in som
263 for (uint8_t iRda = 0; iRda < nRda; iRda++) {
264 ++iWord;
265 curWord = static_cast<uint64_t>(msContent[(iWord)]);
267 LOG(error) << "[CbmMcbm2018UnpackerAlgoTrdR::ProcessMs] Incomplete Spadic "
268 "Message! RDA Word missing, Microslice corrupted.";
269 return kFALSE;
270 }
272 for (uint8_t j = 0; curSample < nSamples && curSample < 32 && j < 7; curSample++, j++) {
273 raw.SetSample(ExtractSample(curWord, curSample), curSample);
274 }
275 }
276 }
278
280 std::shared_ptr<CbmTrdDigi> digi = MakeDigi(raw);
281 if (digi) fTrdDigiVector->emplace_back(*digi);
283 if (fbDebugWriteOutput && (fTrdRawMessageVector != nullptr)) { fTrdRawMessageVector->emplace_back(raw); }
284
287 FillHistograms(); // fill histograms not based on digi or rawMessage input
288 if (digi && fbMonitorMode)
289 if (!FillHistograms(*digi)) LOG(error) << "Failed to fill CbmTrdDigi histograms"; // fill digi histograms
291 if (!FillHistograms(raw))
292 LOG(error) << "Failed to fill CbmTrdRawMessageSpadic histograms"; // fill rawMessage histograms
293 }
294 } // endif (wordType == kSOM )
295
296 if (wordType == Spadic::MsMessageType::kRDA) {
297 LOG(error) << "[CbmMcbm2018UnpackerAlgoTrdR::ProcessMs] Unexpected RDA "
298 "Word. Microslice corrupted.";
299 fNbWildRda++;
300 return kFALSE;
301 }
302
303 if (wordType == Spadic::MsMessageType::kINF) {
305 if (fbDebugWriteOutput && (fSpadicInfoMsgVector != nullptr)) {
306 fSpadicInfoMsgVector->emplace_back(std::make_pair(fLastFulltime, curWord));
307 }
309
310 Spadic::MsInfoType infoType = GetInfoType(curWord);
311 // "Spadic_Info_Types";
313 ((TH2I*) fHistoArray.At(kSpadic_Info_Types))->Fill(fLastFulltime, (Int_t) infoType);
314 }
315 }
316
317 if (wordType == Spadic::MsMessageType::kNUL) {
318 if (iWord != (msNbWords - 1)) // last word in Microslice is 0.
319 {
320 LOG(error) << "[CbmMcbm2018UnpackerAlgoTrdR::ProcessMs] Null Word but "
321 "not at end of Microslice.";
322 }
323 }
324 if (wordType == Spadic::MsMessageType::kUNK) {
325 LOG(error) << "[CbmMcbm2018UnpackerAlgoTrdR::ProcessMs] Unknown Word. "
326 "Microslice corrupted.";
328 //return kFALSE ;
329 }
330
331 if (wordType == Spadic::MsMessageType::kEPO) {
332 uint64_t mask = 0x3FFFFFFF;
333 mask = mask << 32;
334 uint64_t uTS_MSB = (uint64_t)((curWord & mask) >> 32);
335 Long64_t dt_epoch = uTS_MSB - fSpadicEpoch;
336 if (dt_epoch != 1) LOG(debug4) << "[CbmMcbm2018UnpackerAlgoTrdR::ProcessMs] dt_epoch = " << dt_epoch;
337
338 //fLastFulltime = uTS_MSB;
340 fSpadicEpoch = uTS_MSB;
341 }
342
343 } // end for (uint32_t iWord = 0; iWord < msNbWords; iWord++)
344
345 return kTRUE;
346}
347
348void CbmMcbm2018UnpackerAlgoTrdR::AddMsComponentToList(size_t component, UShort_t usDetectorId)
349{
351 for (UInt_t uCompIdx = 0; uCompIdx < fvMsComponentsList.size(); ++uCompIdx)
352 if (component == fvMsComponentsList[uCompIdx]) return;
353
355 fvMsComponentsList.emplace_back(component);
356
357 LOG(info) << "CbmMcbm2018UnpackerAlgoTrdR::AddMsComponentToList => Component " << component << " with detector ID 0x"
358 << std::hex << usDetectorId << std::dec << " added to list";
359}
360
361void CbmMcbm2018UnpackerAlgoTrdR::SetNbMsInTs(size_t uCoreMsNb, size_t uOverlapMsNb)
362{
364 fuNbCoreMsPerTs = uCoreMsNb;
366 fuNbOverMsPerTs = uOverlapMsNb;
367}
368
370{
371 if (!fbMonitorMode && !fbDebugMonitorMode) return kFALSE;
372
373 fHistoArray.SetOwner(kTRUE);
374
375 Bool_t createHistosOk = kTRUE;
377 for (auto isActive : fIsActiveHistoVec) {
378 if (isActive) { createHistosOk &= CreateHistogram((ECbmTrdUnpackerHistograms) iHisto); }
379 iHisto++;
380 }
381
382 return createHistosOk;
383}
384
385// ---- CreateHistogram ----
387{
388 Bool_t createHistoOk = kFALSE;
389 TString histName = "";
390 TH1* newHisto = nullptr;
391 std::map<Int_t, CbmTrdParMod*> parDigiModuleMap = (std::map<Int_t, CbmTrdParMod*>) fDigiPar->GetModuleMap();
392 // Raw Message Histos still need to be separated into module wise histo
393 for (auto mapIt : parDigiModuleMap) {
394 CbmTrdParModDigi* parDigiModule = (CbmTrdParModDigi*) mapIt.second;
395 Int_t moduleId = parDigiModule->GetModuleId();
396 histName.Form("Module%d-", moduleId);
397 switch (iHisto) {
399 histName += "RawMessage_Signalshape_all";
400 newHisto = new TH2I(histName.Data(), histName.Data(), 32, -0.5, 31.5, 512, -256.5, 255.5);
401 newHisto->SetXTitle("time [cc]");
402 newHisto->SetYTitle("Pulse height [ADC channels]");
403 break;
405 histName += "RawMessage_Signalshape_St";
406 newHisto = new TH2I(histName.Data(), histName.Data(), 32, -0.5, 31.5, 512, -256.5, 255.5);
407 newHisto->SetXTitle("time [cc]");
408 newHisto->SetYTitle("Pulse height [ADC channels]");
409 break;
411 histName += "RawMessage_Signalshape_Nt";
412 newHisto = new TH2I(histName.Data(), histName.Data(), 32, -0.5, 31.5, 512, -256.5, 255.5);
413 newHisto->SetXTitle("time [cc]");
414 newHisto->SetYTitle("Pulse height [ADC channels]");
415 break;
417 histName += "RawMessage_Signalshape_filtered";
418 newHisto = new TH2I(histName.Data(), histName.Data(), 32, -0.5, 31.5, 512, -256.5, 255.5);
419 break;
421 histName += "RawDistributionMapModule5";
422 newHisto = new TH2I(histName.Data(), histName.Data(), 42, -0.5, 41.5, 16, -0.5, 15.5);
423 break;
424 case kRawHitType:
425 histName += "RawHitTypes";
426 newHisto =
427 new TH1I(histName.Data(), histName.Data(), ((Int_t) Spadic::eTriggerType::kSandN + 1),
428 ((Int_t) Spadic::eTriggerType::kGlobal - 0.5), ((Int_t) Spadic::eTriggerType::kSandN) + 0.5);
429 break;
430 case kRawPulserDeltaT:
431 histName += "RawPulserDeltaT";
432 newHisto = new TH1I(histName.Data(), histName.Data(), 40000, 0, 4000000);
433 newHisto->SetXTitle("#Delta t [cc]");
434 newHisto->SetYTitle("Counts");
435 break;
437 histName += "Spadic_Info_Types";
438 newHisto = new TH2I(histName.Data(), histName.Data(), 500000, 0, 5e9, 5, -0.5, 4.5);
439 ((TH2I*) newHisto)->SetXTitle("t /Clockcycles");
440 ((TH2I*) newHisto)->SetYTitle("messagetype");
441 ((TH2I*) newHisto)->GetYaxis()->SetBinLabel(1, "BOM");
442 ((TH2I*) newHisto)->GetYaxis()->SetBinLabel(2, "MSB");
443 ((TH2I*) newHisto)->GetYaxis()->SetBinLabel(3, "BUF");
444 ((TH2I*) newHisto)->GetYaxis()->SetBinLabel(4, "UNU");
445 ((TH2I*) newHisto)->GetYaxis()->SetBinLabel(5, "MIS");
446 break;
448 histName += "DigiPulserDeltaT";
449 newHisto = new TH1I(histName.Data(), histName.Data(), 60000, 0, 6e8);
450 newHisto->SetXTitle("#Delta t [ns]");
451 newHisto->SetYTitle("Counts");
452 break;
453 case kDigiDeltaT:
454 histName += "DigiDeltaT";
455 newHisto = new TH1I(histName.Data(), histName.Data(), 6000, -10, ((6e7) - 10));
456 // FIXME this should be more flexibel and made available for all modules of a given geometry
457 fLastDigiTimeVec = std::vector<size_t>(((CbmTrdParModDigi*) fDigiPar->GetModulePar(5))->GetNofColumns()
458 * ((CbmTrdParModDigi*) fDigiPar->GetModulePar(5))->GetNofRows(),
459 0);
460 newHisto->SetXTitle("#Delta t [ns]");
461 newHisto->SetYTitle("Counts");
462 break;
464 histName += "DigiMeanHitFrequency";
465 newHisto =
466 new TProfile(histName.Data(), histName.Data(), parDigiModule->GetNofColumns() * parDigiModule->GetNofRows(),
467 -0.5, parDigiModule->GetNofColumns() * parDigiModule->GetNofRows() - 0.5);
468 // FIXME this should be more flexibel and made available for all modules of a given geometry
469 fLastDigiTimeVec = std::vector<size_t>(((CbmTrdParModDigi*) fDigiPar->GetModulePar(5))->GetNofColumns()
470 * ((CbmTrdParModDigi*) fDigiPar->GetModulePar(5))->GetNofRows(),
471 0);
472 newHisto->SetXTitle("Pad-Channel");
473 newHisto->SetYTitle("Hit frequency [kHz]");
474 break;
476 histName += "DigiDistributionMap";
477 newHisto = new TH2I(histName.Data(), histName.Data(), parDigiModule->GetNofColumns(), -0.5,
478 (parDigiModule->GetNofColumns() - 0.5), parDigiModule->GetNofRows(), -0.5,
479 (parDigiModule->GetNofRows() - 0.5));
480 // newHisto = new TH2I(histName.Data(), histName.Data(), 128, -0.5, 127.5, 6, -0.5, 5.5); // invert row value since they are count from top to bottom
481 newHisto->SetXTitle("Pad column");
482 newHisto->SetYTitle("Pad row");
483 break;
485 histName += "DigiDistributionMapSt";
486 newHisto = new TH2I(histName.Data(), histName.Data(), parDigiModule->GetNofColumns(), -0.5,
487 (parDigiModule->GetNofColumns() - 0.5), parDigiModule->GetNofRows(), -0.5,
488 (parDigiModule->GetNofRows() - 0.5));
489 // newHisto = new TH2I(histName.Data(), histName.Data(), 128, -0.5, 127.5, 6, -0.5, 5.5); // invert row value since they are count from top to bottom
490 newHisto->SetXTitle("Pad column");
491 newHisto->SetYTitle("Pad row");
492 break;
494 histName += "DigiDistributionMapNt";
495 newHisto = new TH2I(histName.Data(), histName.Data(), parDigiModule->GetNofColumns(), -0.5,
496 (parDigiModule->GetNofColumns() - 0.5), parDigiModule->GetNofRows(), -0.5,
497 (parDigiModule->GetNofRows() - 0.5));
498 // newHisto = new TH2I(histName.Data(), histName.Data(), 128, -0.5, 127.5, 6, -0.5, 5.5); // invert row value since they are count from top to bottom
499 newHisto->SetXTitle("Pad column");
500 newHisto->SetYTitle("Pad row");
501 break;
503 histName += "DigiChargeSpectrum";
504 newHisto = new TH1I(histName.Data(), histName.Data(), 512, 0, 512);
505 newHisto->SetYTitle("Counts");
506 newHisto->SetXTitle("MaxAdc [ADC channels]");
507 break;
509 histName += "DigiChargeSpectrumSt";
510 newHisto = new TH1I(histName.Data(), histName.Data(), 512, 0, 512);
511 newHisto->SetYTitle("Counts");
512 newHisto->SetXTitle("MaxAdc [ADC channels]");
513 break;
515 histName += "DigiChargeSpectrumNt";
516 newHisto = new TH1I(histName.Data(), histName.Data(), 512, 0, 512);
517 newHisto->SetYTitle("Counts");
518 newHisto->SetXTitle("MaxAdc [ADC channels]");
519 break;
521 histName += "DigiRelativeTimeMicroslice";
522 newHisto = new TH1D(histName.Data(), histName.Data(), fdMsSizeInNs, 0, fdMsSizeInNs);
523 break;
524 case kDigiTriggerType:
525 histName += "DigiTriggerType";
526 newHisto = new TH1I(histName.Data(), histName.Data(), static_cast<Int_t>(CbmTrdDigi::eTriggerType::kNTrg), -0.5,
527 (static_cast<Int_t>(CbmTrdDigi::eTriggerType::kNTrg) - 0.5));
528 break;
530 histName += "DigiHitFrequency";
531 newHisto = new TProfile(histName.Data(), histName.Data(), 100000, 0, 100000);
532 newHisto->SetXTitle("Timeslice");
533 newHisto->SetYTitle("#langle hit frequency #rangle");
534 break;
535 default: return createHistoOk; break;
536 }
537 LOG(debug4) << Form("UnpackerTrdAlgo - Histo[%d]-%s - initialize", iHisto, histName.Data());
538 if (newHisto) {
539 TString moduleName(Form("%d", moduleId));
540 if (iHisto < kBeginDigiHistos) { fHistoArray.AddAtAndExpand(newHisto, iHisto); }
541 else {
542 Int_t bitShift = Int_t(std::log2(std::double_t(kEndDefinedHistos))) + 1;
543 Int_t histoPosition = moduleId << bitShift;
544 histoPosition += iHisto;
545 if (iHisto >= kBeginDigiHistos) fHistoArray.AddAtAndExpand(newHisto, histoPosition);
546 }
547 // If new HistosTypes are added, they need to be added here!
548 if (newHisto->IsA() == TProfile::Class()) AddHistoToVector((TProfile*) newHisto, moduleName.Data());
549
550 if (newHisto->IsA() == TH2I::Class()) AddHistoToVector((TH2I*) newHisto, moduleName.Data());
551
552 if (newHisto->IsA() == TH1I::Class()) AddHistoToVector((TH1I*) newHisto, moduleName.Data());
553
554 if (newHisto->IsA() == TH1D::Class()) AddHistoToVector((TH1D*) newHisto, moduleName.Data());
555
556 createHistoOk = kTRUE;
557 }
558 }
559 return createHistoOk;
560}
561
563
564// ---- FillHistograms(CbmTrdDigi) ----
566{
567 Bool_t isOkFill = kTRUE;
568 Int_t channelAddress = digi.GetAddressChannel();
569 Int_t histoBaseId = digi.GetAddressModule() << (Int_t(std::log2(std::double_t(kEndDefinedHistos))) + 1);
570
571 // Get the digi triggertype
572 auto triggertype = static_cast<CbmTrdDigi::eTriggerType>(digi.GetTriggerType());
573
574 //Digi position monitoring
578 Int_t rotatedAddress = parModDigi->GetOrientation() == 2
579 ? (channelAddress * (-1) + (parModDigi->GetNofRows() * parModDigi->GetNofColumns()) - 1)
580 : channelAddress;
581 Int_t row = parModDigi->GetPadRow(rotatedAddress);
582 Int_t column = parModDigi->GetPadColumn(rotatedAddress);
583
584 // "DigiDistributionModule5"
586 ((TH2I*) fHistoArray.At(histoBaseId + kDigiDistributionMap))->Fill(column, row);
587 }
589 if (digi.GetAddressModule() == 5 && triggertype == CbmTrdDigi::eTriggerType::kSelf)
590 ((TH2I*) fHistoArray.At(histoBaseId + kDigiDistributionMapSt))->Fill(column, row);
591 }
593 if (digi.GetAddressModule() == 5 && triggertype == CbmTrdDigi::eTriggerType::kNeighbor)
594 ((TH2I*) fHistoArray.At(histoBaseId + kDigiDistributionMapNt))->Fill(column, row);
595 }
596 }
597 // "DigiRelativeTinTimeslice"
599 size_t digiTime = digi.GetTime();
600 size_t deltaT = digiTime - (fSpadicEpoch * fdMsSizeInCC * 62.5); // in clockcycles
601 ((TH1D*) fHistoArray.At(histoBaseId + kDigiRelativeTimeMicroslice))->Fill(deltaT);
602 }
603 // "kDigiChargeSpectrum"
605 ((TH1I*) fHistoArray.At(histoBaseId + kDigiChargeSpectrum))->Fill(digi.GetCharge());
606 }
607 // "kDigiChargeSpectrumSt"
609 if (triggertype == CbmTrdDigi::eTriggerType::kSelf)
610 ((TH1I*) fHistoArray.At(histoBaseId + kDigiChargeSpectrumSt))->Fill(digi.GetCharge());
611 }
612 // "kDigiChargeSpectrumNt"
614 if (triggertype == CbmTrdDigi::eTriggerType::kNeighbor)
615 ((TH1I*) fHistoArray.At(histoBaseId + kDigiChargeSpectrumNt))->Fill(digi.GetCharge());
616 }
617 // "kDigiChargeSpectrumNt"
619 ((TH1I*) fHistoArray.At(histoBaseId + kDigiTriggerType))->Fill(digi.GetTriggerType());
620 }
621
622
623 // "kDigiDeltaT" // DigiPulserDeltaT // "kDigiMeanHitFrequency" // FIXME this works currently with only one module
626 size_t dt = ((size_t) digi.GetTime() - fLastDigiTimeVec.at(channelAddress));
627 if (dt > 0) {
628 // "kDigiDeltaT"
629 if (fIsActiveHistoVec[kDigiDeltaT]) { ((TH1I*) fHistoArray.At(histoBaseId + kDigiDeltaT))->Fill(dt); }
630 // "kDigiMeanHitFrequency"
632 if (dt > 0 && dt < fdTsFullSizeInNs) {
633 Double_t hitFreq = (Double_t) dt;
634 hitFreq *= 1e-9;
635 hitFreq = 1.0 / hitFreq;
636 hitFreq /= 1000.0;
637 ((TProfile*) fHistoArray.At(histoBaseId + kDigiMeanHitFrequency))->Fill(channelAddress, hitFreq);
638 }
639 }
640 // DigiPulserDeltaT
642 Int_t pulserChannelAddress(663); // status 03/27/2020
643 Int_t pulserModule(5); // status 03/27/2020
644 if (channelAddress == pulserChannelAddress && digi.GetAddressModule() == pulserModule
645 && triggertype == CbmTrdDigi::eTriggerType::kSelf) {
646 ((TH1I*) fHistoArray.At(histoBaseId + kDigiPulserDeltaT))->Fill(dt);
647 }
648 }
649 // "kDigiMeanHitFrequency"
651 if (dt > 0 && dt < fdTsFullSizeInNs) {
652 Int_t tsCounter = fNbTimeslices % ((TProfile*) fHistoArray.At(histoBaseId + kDigiHitFrequency))->GetNbinsX();
653 Double_t hitFreq = (Double_t) dt;
654 hitFreq *= 1e-9;
655 hitFreq = 1.0 / hitFreq;
656 hitFreq /= 1000.0;
657 ((TProfile*) fHistoArray.At(histoBaseId + kDigiHitFrequency))->Fill(tsCounter, hitFreq);
658 if (tsCounter == 0) ((TProfile*) fHistoArray.At(histoBaseId + kDigiHitFrequency))->Reset();
659 }
660 }
661 fLastDigiTimeVec.at(channelAddress) = (size_t) digi.GetTime();
662 }
663 }
664 return isOkFill;
665}
666
667// ---- FillHistograms(CbmTrdSpadicRawMessage) ----
669{
670 Bool_t isOkFill = kTRUE;
671 // "RawMessage_Signalshape_filtered"
673 if (raw.GetHitType() < 2 && !raw.GetMultiHit()) {
674 for (unsigned int i = 0; i < raw.GetSamples()->size(); i++) {
675 ((TH2I*) fHistoArray.At(kRawMessage_Signalshape_filtered))->Fill(i, raw.GetSamples()->at(i));
676 }
677 }
678 }
679 // "RawMessage_Signalshape_all"
681 for (unsigned int i = 0; i < raw.GetSamples()->size(); i++) {
682 //fHistoMap.at(HistName.Data())->Fill(i, raw.GetSamples()->at(i));
683 ((TH2I*) fHistoArray.At(kRawMessage_Signalshape_all))->Fill(i, raw.GetSamples()->at(i));
684 }
685 }
686 // "kRawMessage_Signalshape_St"
688 for (unsigned int i = 0; i < raw.GetSamples()->size(); i++) {
689 if (raw.GetHitType() == (Int_t) Spadic::eTriggerType::kSelf
690 || raw.GetHitType() == (Int_t) Spadic::eTriggerType::kSandN)
691 ((TH2I*) fHistoArray.At(kRawMessage_Signalshape_St))->Fill(i, raw.GetSamples()->at(i));
692 }
693 }
694 // "kRawMessage_Signalshape_Nt"
696 for (unsigned int i = 0; i < raw.GetSamples()->size(); i++) {
697 if (raw.GetHitType() == (Int_t) Spadic::eTriggerType::kNeigh)
698 ((TH2I*) fHistoArray.At(kRawMessage_Signalshape_Nt))->Fill(i, raw.GetSamples()->at(i));
699 }
700 }
701 // "RawDistributionMapModule5"
703 ((TH1I*) fHistoArray.At(kRawDistributionMapModule5))->Fill(raw.GetElinkId(), raw.GetChannelId());
704 }
705 // "kRawHitType"
706 if (fIsActiveHistoVec[kRawHitType]) { ((TH1I*) fHistoArray.At(kRawHitType))->Fill(raw.GetHitType()); }
707 // "RawPulserDeltaT"
709 std::uint8_t pulserChannelId = 0; // status 03/27/2020
710 std::uint8_t pulserElinkId = 29; // status 03/27/2020
711 if (raw.GetChannelId() == pulserChannelId && raw.GetElinkId() == pulserElinkId) {
712 Long64_t dt = ((Long64_t) raw.GetFullTime() - (Long64_t) fLastFulltime);
713 ((TH1I*) fHistoArray.At(kRawPulserDeltaT))->Fill(dt);
715 }
716 }
717 return isOkFill;
718}
719
720// ---- CbmMcbm2018UnpackerAlgoTrdR::ResetHistograms() ----
722{
723 /*
724 for ( auto &it : fHistoMap )
725 {
726 it.second->Reset() ;
727 }
728 */
729
730 for (auto it = fHistoArray.begin(); it != fHistoArray.end(); ++it) {
731 ((TH1*) *it)->Reset();
732 }
733 return kTRUE;
734}
735
736Bool_t CbmMcbm2018UnpackerAlgoTrdR::SetDigiOutputPointer(std::vector<CbmTrdDigi>* const pVector)
737{
738 if (nullptr == fTrdDigiVector) {
739 fTrdDigiVector = pVector;
740 return kTRUE;
741 }
742 else {
743 return kFALSE;
744 }
745}
746
747Bool_t CbmMcbm2018UnpackerAlgoTrdR::SetRawOutputPointer(std::vector<CbmTrdRawMessageSpadic>* const pVector,
748 std::vector<std::pair<size_t, size_t>>* const qVector)
749{
750 Bool_t ret = 1;
751 if (nullptr == fTrdRawMessageVector) { fTrdRawMessageVector = pVector; }
752 else {
753 ret &= 0;
754 }
755
756 if (qVector != nullptr && fSpadicInfoMsgVector == nullptr) { fSpadicInfoMsgVector = qVector; }
757 else {
758 ret &= 0;
759 }
760 return ret;
761}
762
763// --------- private: -----------
764
766{
767 Int_t digiAddress = -1;
768 Float_t digiCharge =
769 (Float_t) raw.GetMaxAdc()
770 + 256; // REMARK raw.GetMaxADC returns a the value in the range of -256 til 255. However, the digiCharge is stored as unsigned. // TODO make Settable
771
772 // Int_t digiTriggerType = raw.GetHitType() ; // Spadic::eTriggerType this does not work 03/27/2020 - PR digiTriggerType is not Spadic::eTriggerType!
773 Int_t rawTriggerType = raw.GetHitType();
774 auto digiTriggerType = CbmTrdDigi::eTriggerType::kNTrg;
775 if (rawTriggerType == 1) digiTriggerType = CbmTrdDigi::eTriggerType::kSelf; // Shift self trigger to digi selftrigger
776 if (rawTriggerType == 2)
777 digiTriggerType = CbmTrdDigi::eTriggerType::kNeighbor; // Shift neighbour trigger to digi neighbour
778 if (rawTriggerType == 3) digiTriggerType = CbmTrdDigi::eTriggerType::kSelf; // Hide spadic kSandN in Self
779
780 Int_t digiErrClass = 0;
781
782 size_t spadicHwAddress(0);
783 spadicHwAddress = (raw.GetElinkId()) + (CbmTrdParAsic::kCriIdPosition * raw.GetCriId())
785 Int_t asicAddress(0);
786 auto mapIt = fSpadicMap.find(spadicHwAddress); // check if asic exists
787 if (mapIt == fSpadicMap.end()) {
788 LOG(debug4) << "CbmMcbm2018UnpackerAlgoTrdR::MakeDigi - No asic address "
789 "found for Spadic hardware address %lu"
790 << spadicHwAddress;
791 return nullptr;
792 }
793 asicAddress = mapIt->second;
794 Int_t uniqueModuleId = asicAddress / 1000;
795 // Int_t layerId(CbmTrdAddress::GetLayerId(uniqueModuleId));
796 // Int_t moduleId(CbmTrdAddress::GetModuleId(uniqueModuleId));
797
798 // GetChannelId per eLink add NSPADICCH / 2 to the second(first) eLink in the case we start with odd(even) eLinks, since, our mapping is based on odd eLinks
799 auto asicChannelId =
800 (raw.GetElinkId() % 2) == fIsFirstChannelsElinkEven ? raw.GetChannelId() : raw.GetChannelId() + (NSPADICCH / 2);
801
802 digiAddress = (fAsicChannelMap.find(asicAddress))->second.at(asicChannelId);
803
804 ULong64_t digiTime = raw.GetTime();
805 if (fvecTimeshiftsPar) {
806 digiTime = digiTime - fvecTimeshiftsPar->at(digiAddress);
807 raw.SetTime(digiTime);
808 }
809 digiTime -= fdTimeOffsetNs;
810
811 std::shared_ptr<CbmTrdDigi> digi = std::make_shared<CbmTrdDigi>(
812 CbmTrdDigi(digiAddress, uniqueModuleId, digiCharge, digiTime, digiTriggerType, digiErrClass));
813
814 return digi;
815}
816
818{
819 if ((msg >> 61) == 1) // SOM 001. ....
820 {
822 }
823 else if ((msg >> 63) == 1) // RDA 1... ....
824 {
826 }
827 else if ((msg >> 62) == 1) // Epoch 01.. ....
828 {
830 }
831 else if ((msg >> 60) == 1) // Spadic Info Message 0001 ....
832 {
834 }
835 else if (msg == 0) // Last Word in a Microslice is 0
836 {
838 }
839 else // not a spadic message
840 {
842 }
843}
844
846{
847 uint64_t mask = 0x000FFFFF;
848
849 if (((msg & mask) >> 18) == 3) // BOM
850 {
852 }
853 if (((msg & mask) >> 17) == 2) // MSB
854 {
856 }
857 if (((msg & mask) >> 17) == 3) // BUF
858 {
860 }
861 if (((msg & mask) >> 17) == 4) // UNU
862 {
864 }
865 if (((msg & mask) >> 17) == 5) // MIS
866 {
868 }
869 else {
870 LOG(error) << "[CbmMcbm2018UnpackerAlgoTrdR::GetInfoType] unknown type!";
872 }
873}
874
876 fles::MicrosliceDescriptor msDesc)
877{
879 LOG(error) << "[CbmMcbm2018UnpackerAlgoTrdR::CreateRawMessage] Not a SOM word!";
880 return CbmTrdRawMessageSpadic();
881 }
883 uint8_t elinkId = 0, chId = 0, crobId = 0;
884 uint16_t criId = msDesc.eq_id;
885 // char crobId = msDesc.crob_id; // TODO this needs to be implemented into microslice! - PR 03.2020
886 uint8_t hitType = 0, nSamples = 0;
887 bool multihit = false;
888 uint16_t timestamp = 0;
889 uint64_t mask = 0x3F;
890 mask = mask << 55;
891 elinkId = (char) ((word & mask) >> 55);
892 //extract chID
893 mask = 0xF;
894 mask = mask << 51;
895 chId = (char) ((word & mask) >> 51);
896 //extract timestamp
897 mask = 0xFFFF;
898 mask = mask << 35;
899 timestamp = (uint16_t)((word & mask) >> 35);
900 //extract hitType
901 mask = 0x3;
902 mask = mask << 33;
903 hitType = (uint8_t)((word & mask) >> 33);
904 //extract MultiHit
905 mask = 0x1;
906 mask = mask << 32;
907 multihit = (bool) ((word & mask) >> 32);
908 //extract nrSamples
909 mask = 0x1F;
910 mask = mask << 27;
911 nSamples = (uint8_t)((word & mask) >> 27);
912 nSamples += 1; //spadic counts from 0 to 31
913
914 // get the correct fulltime
915 uint64_t fulltime = timestamp + (fSpadicEpoch * fdMsSizeInCC); // this is in units of clock cycles
916 //uint64_t epoch = fSpadicEpoch >> 3 ;
917
918
919 // put the first 3 samples, contained in som, into the message.
920 std::vector<int16_t> samples;
921 for (int i = 0; i < nSamples && i < 3; i++) {
922 samples.emplace_back(ExtractSample(word, i, multihit));
923 }
924
925 // Create message
926 CbmTrdRawMessageSpadic retval(chId, elinkId, crobId, criId, hitType, nSamples, multihit, fulltime, samples);
927 return retval;
928}
929
931{
932 if (nsamples < 4) return 0;
933 else if (nsamples < 11)
934 return 1;
935 else if (nsamples < 18)
936 return 2;
937 else if (nsamples < 25)
938 return 3;
939 else if (nsamples < 32)
940 return 4;
941 else
942 return 5;
943}
944
945int16_t CbmMcbm2018UnpackerAlgoTrdR::ExtractSample(const uint64_t word, uint8_t sample, Bool_t multihit)
946{
947 const std::array<uint16_t, 32> indices {
948 {4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0}};
949 uint64_t mask = 0x1FF;
952 LOG(error) << "[CbmMcbm2018UnpackerAlgoTrdR::ExtractSample] Wrong Message Type!";
953 return -256;
954 }
955
956 if ((GetMessageType(word) == Spadic::MsMessageType::kSOM) && (sample > 2)) {
957 LOG(error) << "[CbmMcbm2018UnpackerAlgoTrdR::ExtractSample] Wrong sample index!";
958 return -256;
959 }
960 if ((GetMessageType(word) == Spadic::MsMessageType::kRDA) && (sample < 3 || sample > 31)) {
961 LOG(error) << "[CbmMcbm2018UnpackerAlgoTrdR::ExtractSample] Wrong sample index!";
962 return -256;
963 }
964 uint16_t index = indices[sample];
965
966 mask = mask << (9 * (6 - index));
967 uint64_t temp = word & mask;
968 temp = temp >> (6 - index) * 9;
969 if (fbBaselineAvg && (sample == 0) && !(multihit)) {
977 temp = temp >> 2;
978 temp ^= (-0 ^ temp) & (1 << 7);
979 temp ^= (-1 ^ temp) & (1 << 8);
980 }
981 struct {
982 signed int x : 9;
983 } s;
984 int16_t result = s.x = temp;
985 return result;
986}
987
ClassImp(CbmConverterManager)
Helper class to convert unique channel ID back and forth.
#define NSPADICCH
static constexpr size_t size()
Definition KfSimdPseudo.h:2
Timeslice unpacker algorithm for Spadic v.2.2 .
ULong64_t fNbSpadicErrorMsg
Number of Spadic error Messages.
ULong64_t fNbUnkownWord
Number of unknown data words in the Microslice stream.
std::map< Int_t, std::vector< Int_t > > fAsicChannelMap
Map to retrieve module channelId from asicAddress and asicChannel.
CbmTrdParSetDigi * fDigiPar
CbmTrdParameter container.
Bool_t ProcessTs(const fles::Timeslice &ts)
std::vector< bool > fIsActiveHistoVec
Stores all Histograms.
Double_t fTsStartTime
Time in ns of current TS from the index of the first MS first componen.
bool fIsFirstChannelsElinkEven
define if the first 16 channels (00..15) are found on the even (set true) or odd (false) eLinkId,...
std::map< size_t, Int_t > fSpadicMap
Map to retrieve asic address from CriId/CrobId/ElinkId (see CbmTrdHardwareSetupR)
Spadic::MsMessageType GetMessageType(const uint64_t msg)
Bool_t CreateHistograms()
Goes through fIsActiveHistoVec and creates the activated histograms.
Bool_t fbBaselineAvg
Set to true if Baseline Averaging is activated in Spadic.
Bool_t ProcessMs(const fles::Timeslice &ts, size_t uMsCompIdx, size_t uMsIdx)
Unpacks one Microslice.
Bool_t fbMonitorMode
Switch ON the filling of a minimal set of histograms.
void AddMsComponentToList(size_t component, UShort_t usDetectorId)
CbmTrdParSetGain * fGainPar
CbmTrdParameter container.
int16_t ExtractSample(const uint64_t word, uint8_t sample, Bool_t multihit=kFALSE)
Extract a Sample from a given SOM or RDA word.
ULong64_t fNbWildRda
Number of RDA Words outside of a Message.
CbmTrdRawMessageSpadic CreateRawMessage(const uint64_t word, fles::MicrosliceDescriptor msDesc)
Bool_t SetDigiOutputPointer(std::vector< CbmTrdDigi > *const pVector)
Set fTrdDigiVector to the address of pVector.
std::vector< CbmTrdRawMessageSpadic > * fTrdRawMessageVector
Output Spadic raw messages for debugging.
Bool_t fbDebugWriteOutput
If ON the raw messages output vector is filled and written to disk.
ULong64_t fNbTimeslices
Instance of RawToDigi class.
ULong64_t fNbSpadicEpochMsg
Number of Spadic Epoch Messages.
Spadic::MsInfoType GetInfoType(const uint64_t msg)
Bool_t fbDebugSortOutput
If ON the raw messages output vector is sorted within time.
std::map< size_t, std::vector< Int_t > > fmapTimeshifts
Map containing the timeshift parameters for the correction of the µSlice timeshifts....
Double_t fdTimeOffsetNs
User settings: Data correction parameters.
ULong64_t fCurrTsIdx
Index of current Timeslice.
CbmTrdParSetAsic * fAsicPar
CbmTrdParameter container.
std::vector< std::pair< size_t, size_t > > * fSpadicInfoMsgVector
vector< pair< fulltime, word > >
std::shared_ptr< CbmTrdDigi > MakeDigi(CbmTrdRawMessageSpadic raw)
std::vector< CbmTrdDigi > * fTrdDigiVector
Output Digi vector.
void SetNbMsInTs(size_t uCoreMsNb, size_t uOverlapMsNb)
CbmTrdParSetGas * fGasPar
CbmTrdParameter container.
Bool_t SetRawOutputPointer(std::vector< CbmTrdRawMessageSpadic > *const pVector, std::vector< std::pair< size_t, size_t > > *const qVector=nullptr)
Set fTrdRawMessageVector to the address of pVector.
ULong64_t fSpadicEpoch
Epoch counter (30 bits). Counts overflow of Spadic timestamp (11 bits).
Bool_t fbDebugMonitorMode
Switch ON the filling of a additional set of histograms.
std::vector< Int_t > * fvecTimeshiftsPar
Vector containing the timeshift parameters for the correction of the µSlice timeshifts for a given ts...
static const UInt_t kBytesPerWord
Constants.
Bool_t CreateHistogram(ECbmTrdUnpackerHistograms iHisto)
create the histogram correlated to iHisto
TList * fParContList
Parameters and Address mapping.
void AddHistoToVector(TNamed *pointer, std::string sFolder="")
std::vector< size_t > fvMsComponentsList
int32_t GetAddressModule() const
Getter module address in the experiment.
int32_t GetTriggerType() const
Channel trigger type. SPADIC specific see CbmTrdTriggerType.
Definition CbmTrdDigi.h:163
int32_t GetAddressChannel() const
Getter read-out id.
double GetTime() const
Getter for physical time [ns]. Accounts for clock representation of each ASIC. In SPADIC case physica...
Definition CbmTrdDigi.h:153
double GetCharge() const
Common purpose charge getter.
std::map< size_t, Int_t > CreateHwToSwAsicAddressTranslatorMap(bool isLoadedParameters)
Create a hardware to software asic addreess translator map, with hidden parameter loading.
std::map< Int_t, std::vector< Int_t > > CreateAsicChannelMap(bool isLoadedParameters)
Create a Asic Channel Map, with hidden parameter loading.
Definition of chamber gain conversion for one TRD module.
Int_t GetPadRow(const Int_t channelNumber) const
Int_t GetOrientation() const
Int_t GetNofRows() const
Int_t GetPadColumn(const Int_t channelNumber) const
Int_t GetNofColumns() const
virtual int GetModuleId() const
Describe TRD module ASIC settings (electronic gain, delays, etc)
virtual void clear()
Reset all parameters.
Describe TRD module working settings (HV, etc)
virtual const CbmTrdParMod * GetModulePar(Int_t detId) const
std::map< Int_t, CbmTrdParMod * > GetModuleMap()
Base class for storing raw information which comes from the Spadic v2.2 trough flib or from a tsa fil...
std::uint64_t GetFullTime() const
void SetTime(double setvalue)
const std::vector< std::int16_t > * GetSamples() const
std::uint8_t GetChannelId() const
void SetSample(std::int16_t value, std::uint8_t pos)
std::uint8_t GetNrSamples() const
std::uint8_t GetCrobId() const
std::uint8_t GetHitType() const
std::uint8_t GetElinkId() const
std::uint16_t GetCriId() const
@ kUNU
Unused request. 100. .... .... .... cccc.
@ kBOM
Buffer overflow count. 11nn nnnn nnnn nnnn cccc.
@ kMIS
Missing request. 101. .... .... .... ....
@ kBUF
Buffer full. 011b b... .... .... cccc.
@ kMSB
Message build error. 010. .... .... .... cccc.
@ kNeigh
Neighbor trigger.
@ kGlobal
global trigger.
@ kSelf
Self trigger.
@ kSandN
Self and neighbor trigger at the same time.
@ kNUL
Microslice End.
@ kSOM
Start of Message.
@ kEPO
Epoch Marker or TS_MSB depending on the hitmessage version.
@ kUNK
Unkown Word.
@ kINF
Info Message.