CbmRoot
Loading...
Searching...
No Matches
CbmMcbm2018UnpackerAlgoRich2020.cxx
Go to the documentation of this file.
1/* Copyright (C) 2021 Justus-Liebig-Universitaet Giessen, Giessen
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Semen Lebedev [committer] */
4
61//TODO: Check that to 'real' actions are performed in the lines which are intended for debug output only.
62// i.e. LOG(XXXX) << ...
63
65
66// ROOT
67#include <Logger.h>
68
69#include <TCanvas.h>
70#include <TList.h>
71
72// CbmRoot
73#include "CbmMcbm2018RichPar.h"
74
75#include <iostream>
76
79 , fbMonitorMode(kFALSE)
80 , fbDebugMonitorMode(kFALSE)
81 , fRawDataMode(kFALSE)
82 , fError(kFALSE)
83 , fTrbState(TrbNetState::IDLE)
84 , fErrorCorr(0)
85 , fbDoToTCorr(kTRUE)
86 , fSkipMs(kFALSE)
87 , fdTimeOffsetNs(0.0)
88 , fRICHcompIdx(6)
89 , //TODO experimentally obtained value
90 fUnpackPar(nullptr)
91 , fTScounter(0)
92 , fCurMSid(0)
93 , fGwordCnt(0)
94 , fInSubSubEvent(kFALSE)
95 , fCurEpochCounter(0)
96 , fSubSubEvId(0)
97 , fLastCTSch0_re_time(0.)
98 , fLastCTSch2_re_time(0.)
99 , fLastCTSch2_fe_time(0.)
100 , fPrevLastCTSch0_re_time(0.)
101 , fPrevLastCTSch2_re_time(0.)
102 , fPrevLastCTSch2_fe_time(0.)
103 , /*,
104 fhTDCch0re_minusCTSch0re(nullptr),
105 fhTDCch0re_minusCTSch2re(nullptr),
106 fhTDCch0re_minusCTSch2fe(nullptr),
107 fhTDCch0re_minusPrevCTSch0re(nullptr),
108 fhTDCch0re_minusPrevCTSch2re(nullptr),
109 fhTDCch0re_minusPrevCTSch2fe(nullptr)*/
110 fMapFEE()
111 , fhTotMap()
112 , fhTot2dMap()
113{
114 this->Init(); //TODO why this is not called by the framework?
115}
116
118{
119 if (nullptr != fParCList) delete fParCList;
120 if (nullptr != fUnpackPar) delete fUnpackPar;
121}
122
124{
125 LOG(info) << "Initializing mCBM RICH 2019 unpacker algo";
126 //fhDigisInChnl = new TH2D("fhDigisInChnl","fhDigisInChnl;channel;#Digis;" ,2304 , -0.5, 2303.5, 50, -0.5, 49.5);
127 //fhDigisInDiRICH = new TH2D("fhDigisInDiRICH","fhDigisInDiRICH;DiRICH;#Digis;",72 , -0.5, 71.5, 300, -0.5, 299.5);
128 return kTRUE;
129}
130
132
134
136{
137 LOG(info) << "Init parameter containers for CbmMcbm2018UnpackerAlgoRich2020";
138 Bool_t initOK = ReInitContainers();
139
140 return initOK;
141}
142
144{
145 LOG(info) << "ReInit parameter containers for CbmMcbm2018UnpackerAlgoRich2020";
146
147 fUnpackPar = (CbmMcbm2018RichPar*) fParCList->FindObject("CbmMcbm2018RichPar");
148 if (fUnpackPar == nullptr) { return kFALSE; }
149
150 Bool_t initOK = InitParameters();
151
152 return initOK;
153}
154
156{
157 if (fParCList == nullptr) { fParCList = new TList(); }
158 fUnpackPar = new CbmMcbm2018RichPar("CbmMcbm2018RichPar");
159 fParCList->Add(fUnpackPar);
160
161 return fParCList;
162}
163
165{
166 InitStorage();
167 return kTRUE;
168}
169
171{
172 fLastCh0_re_time.Set(fUnpackPar->GetNaddresses()); // Set the size of the array
173 fPrevLastCh0_re_time.Set(fUnpackPar->GetNaddresses()); // Set the size of the array
174}
175
180void CbmMcbm2018UnpackerAlgoRich2020::AddMsComponentToList(size_t component, UShort_t usDetectorId)
181{
183 for (UInt_t uCompIdx = 0; uCompIdx < fvMsComponentsList.size(); ++uCompIdx) {
184 if (component == fvMsComponentsList[uCompIdx]) { return; }
185 }
186
188 fvMsComponentsList.push_back(component);
189
190 if (fvMsComponentsList.size() == 1) { fRICHcompIdx = component; }
191 else {
192 LOG(warning) << "fvMsComponentsList.size() > 1 for RICH. Unpacking may not "
193 "work due to implementation limitations.";
194 }
195
196 LOG(info) << "CbmMcbm2018UnpackerAlgoRich2020::AddMsComponentToList => Component " << component
197 << " with detector ID 0x" << std::hex << usDetectorId << std::dec << " added to list";
198}
199
200Bool_t CbmMcbm2018UnpackerAlgoRich2020::ProcessTs(const fles::Timeslice& /*ts*/)
201{
202 LOG(debug2) << "CbmMcbm2018UnpackerAlgoRich2020::ProcessTs(ts)";
203 /*
204 //TODO: shortcut. We love shortcuts, right?
205 if (fvMsComponentsList.size() == 1) {
206 this->ProcessTs(ts, fvMsComponentsList.at(0));
207 }
208
209 //TODO: implement case when multiple components have to be processed
210*/
211 return kTRUE;
212}
213
214Bool_t CbmMcbm2018UnpackerAlgoRich2020::ProcessTs(const fles::Timeslice& ts, size_t component)
215{
217 if (0 == ts.index()) { return kTRUE; } // if( 0 == ts.index() )
218
219 LOG(debug2) << "CbmMcbm2018UnpackerAlgoRich2020::ProcessTs(ts, " << component << ")";
220
221 //TODO: skip if this method was called for a wrong component
222 //if (component != fRICHcompIdx) return kTRUE;
223 //FIXME: this is really nasty...
224 // component = fRICHcompIdx;
225 if (1 != fvMsComponentsList.size()) {
227 if (0 == fvMsComponentsList.size()) return kTRUE;
228
230 TString sCompList = "";
231 for (UInt_t uMsCompIdx = 0; uMsCompIdx < fvMsComponentsList.size(); ++uMsCompIdx)
232 sCompList += Form(" %2lu ", fvMsComponentsList[uMsCompIdx]);
233 LOG(fatal) << "CbmMcbm2018UnpackerAlgoRich2020::ProcessTs => More than 1 "
234 "component in list, unpacking impossible! List is "
235 << sCompList;
236 } // if( 1 != fvMsComponentsList.size() )
237 component = fvMsComponentsList[0];
238
239 LOG(debug) << "Components: " << ts.num_components();
240 LOG(debug) << "Microslices: " << ts.num_microslices(component);
241
242 const uint64_t compSize = ts.size_component(component);
243 LOG(debug) << "Component " << component << " has size " << compSize;
244
246 if (-1.0 == fdTsCoreSizeInNs) {
247 fuNbCoreMsPerTs = ts.num_core_microslices();
248 fuNbOverMsPerTs = ts.num_microslices(0) - ts.num_core_microslices();
251 LOG(info) << "Timeslice parameters: each TS has " << fuNbCoreMsPerTs << " Core MS and " << fuNbOverMsPerTs
252 << " Overlap MS, for a core duration of " << fdTsCoreSizeInNs << " ns and a full duration of "
253 << fdTsFullSizeInNs << " ns";
254
258 LOG(info) << "In each TS " << fuNbMsLoop << " MS will be looped over";
259 } // if( -1.0 == fdTsCoreSizeInNs )
260
261 for (size_t iMS = 0; iMS < fuNbMsLoop; ++iMS) {
262 fCurMSid = iMS;
263 LOG(debug) << "=======================================================";
264 const fles::MicrosliceView mv = ts.get_microslice(component, iMS);
265 const fles::MicrosliceDescriptor& msDesc = mv.desc();
267 LOG(debug) << "msDesc.size=" << msDesc.size;
268 fCurMSidx = msDesc.idx;
269 LOG(debug) << "msDesc.idx=" << msDesc.idx;
273 //ProcessMs(ts, component, iMS);//
275
276 if (!fRawDataMode) ProcessMs(ts, component, iMS);
277 if (fRawDataMode) DebugMs(ts, component, iMS);
278
279 LOG(debug) << "=======================================================";
280 }
281
283 FinalizeTs(); //
285
286 if (0 == fTScounter % 1000) { LOG(info) << "Processed " << fTScounter << " TS"; }
287
288 fTScounter++;
289
291 std::sort(fDigiVect.begin(), fDigiVect.end(),
292 [](const CbmRichDigi& a, const CbmRichDigi& b) -> bool { return a.GetTime() < b.GetTime(); });
293
295 fhVectorSize->Fill(ts.index(), fDigiVect.size());
296 fhVectorCapacity->Fill(ts.index(), fDigiVect.capacity());
297 } // if( fbMonitorMode || fbDebugMonitorMode )
298
299 if (fuTsMaxVectorSize < fDigiVect.size()) {
301 fDigiVect.shrink_to_fit();
303 } // if( fuTsMaxVectorSize < fDigiVect.size() )
304
305 return kTRUE;
306}
307
308Bool_t CbmMcbm2018UnpackerAlgoRich2020::ProcessMs(const fles::Timeslice& ts, size_t uMsCompIdx, size_t uMsIdx)
309{
310 const fles::MicrosliceView mv = ts.get_microslice(uMsCompIdx, uMsIdx);
311 const fles::MicrosliceDescriptor& msDesc = mv.desc();
312 const uint8_t* ptr = mv.content();
313 const size_t size = msDesc.size;
314
315 if (size == 0) return kTRUE;
316
317 fGwordCnt = 0; //TODO check that this global word counter works properly
318
319 Int_t offset; // offset in bytes
320 Int_t* dataPtr;
321
322 offset = 0;
323 mRichSupport::SwapBytes(4, ptr + offset);
324 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
325 << "ok"
326 << "\t"
327 << "Reserved 0000 0000";
328 fGwordCnt++;
329
330 offset = 4;
331 mRichSupport::SwapBytes(4, ptr + offset);
332 // clang-format off
333 dataPtr = (Int_t*) (ptr + offset);
334 Int_t mbsNumber = (Int_t)(dataPtr[0] & 0xffffff);
335 uint8_t mts_error_msg = (uint8_t)((dataPtr[0] >> 24) & 0xff);
336 // clang-format on
337 ErrorMsg(static_cast<uint16_t>(mts_error_msg), RichErrorType::mtsError);
338 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
339 << "ok"
340 << "\t"
341 << "mbsNumber = " << mbsNumber;
342 fGwordCnt++;
343
344 // We suppose that the first word is
345 // "HadesTransportUnitQueue - Length"
346 offset = 0 + 8;
347 mRichSupport::SwapBytes(4, ptr + offset);
348 // clang-format off
349 dataPtr = (Int_t*) (ptr + offset);
350 Int_t TRBeventSize1 = (Int_t)(dataPtr[0]);
351 // clang-format on
352 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
353 << "ok"
354 << "\t"
355 << "HadesTransportUnitQueue - Length = " << TRBeventSize1;
356 fGwordCnt++;
357
358 if (*dataPtr > 0 && UInt_t(*dataPtr) == 0x80030000) {
359 LOG(info) << "dataPtr == 0x80030000";
360 exit(EXIT_FAILURE);
361 }
362
363 // We suppose that the second word is
364 // "HadesTransportUnitQueue - Decoder (Seems to be allways the same)"
365 offset = 4 + 8;
366 mRichSupport::SwapBytes(4, ptr + offset);
367 // clang-format off
368 dataPtr = (Int_t*) (ptr + offset);
369 Int_t dcdr = (Int_t)(dataPtr[0]);
370 // clang-format on
371 if (dcdr == 0x00030062) {
372 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
373 << "ok"
374 << "\t"
375 << "HadesTransportUnitQueue - Decoder = " << dcdr;
376 fGwordCnt++;
377 }
378 else {
379 LOG(warning) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
380 << "er"
381 << "\t"
382 << "HadesTransportUnitQueue - Decoder = " << dcdr << " is not 0x00030062 (196706) => 0x" << std::hex
383 << dcdr << std::dec;
384 fGwordCnt++;
385
387 fSkipMs = kTRUE;
388 return kFALSE;
389 }
390
391 // We suppose that the third word is
392 // TRB event length (in bytes)
393 // It should be 8 less than the size specified two words ago
394 offset = 8 + 8;
395 mRichSupport::SwapBytes(4, ptr + offset);
396 // clang-format off
397 dataPtr = (Int_t*) (ptr + offset);
398 Int_t TRBeventSize2 = (Int_t)(dataPtr[0]);
399 // clang-format on
400 if (TRBeventSize2 == TRBeventSize1 - 8) {
401 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
402 << "ok"
403 << "\t"
404 << "TRB event - Length = " << TRBeventSize2 << " == " << TRBeventSize1 << "-8";
405 fGwordCnt++;
406 }
407 else {
408 LOG(debug) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
409 << "er"
410 << "\t"
411 << "TRB event - Length = " << TRBeventSize2 << " != " << TRBeventSize1 << "-8=" << TRBeventSize1 - 8;
412 fGwordCnt++;
413 }
414
416 ProcessTRBevent(TRBeventSize2, ptr + offset); //
418
419 // Bytes in a TrbEvent
420 if (fbDebugMonitorMode) fhEventSize->Fill(TRBeventSize2);
421
422
423 if (fSkipMs == kTRUE) {
424 // problem in data; delete vectors.
425 fDigiVect.clear();
426 fSkipMs = kFALSE;
427 }
428
429
430 return kTRUE;
431}
432
433Int_t CbmMcbm2018UnpackerAlgoRich2020::ProcessTRBevent(size_t const size, uint8_t const* const ptr)
434{
435 Int_t offset; // offset in bytes
436 Int_t* dataPtr;
437
438 // We assume that the TRB event header is 4 words and
439 // the first word is already processed outside of this method
440
442 ProcessTRBeventHeader(4 * 4, ptr); //
444
445 offset = 16; // start from after the TRB event header
446
447 // 1. Search for the CTS subevent and extract reference time
448
449 while (static_cast<size_t>(offset) < size) {
451 if (fSkipMs == kTRUE) break;
452
453 // Duplicate the header word in order to avoid corrupting (by bytes swapping)
454 // the original data
455 // clang-format off
456 dataPtr = (Int_t*) (ptr + offset);
457
458 Int_t headerCopy = *dataPtr;
459 mRichSupport::SwapBytes(4, (uint8_t*) &headerCopy);
460 dataPtr = &headerCopy;
461
462 Int_t SubEvSize = (Int_t) ((dataPtr[0] >> 16) & 0xffff);
463 Int_t HubId = (Int_t) ((dataPtr[0]) & 0xffff);
464 // clang-format on
465 // Process only CTS subevent
466 //FIXME change from 0xc001 to 0xc000 at some point // ?
467 if ((HubId == 0xc001) || (HubId == 0xc000)) {
468
469 // Not a very nice shortcut
470 // The global counter of the words is incremented for the CTS subevent header here
471 // However for the TRB subevent headers it is incremented in the second run,
472 // where only TRB subevent headers are processed and the CTS subevents are skipped
473 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr((uint8_t*) &headerCopy) << "\t"
474 << "ok"
475 << "\t"
476 << "hub ID = 0x" << mRichSupport::GetHexRepresentation(2, (uint8_t*) &headerCopy) << "\t"
477 << "subevent size = " << SubEvSize;
478 fGwordCnt++;
479
480 fSubSubEvId = HubId;
482 offset += (4 + ProcessCTSsubevent(SubEvSize * 4, ptr + offset)); //
484
485 //std::cout<<"Words in CTS 0x"<< std::hex << HubId << std::dec <<" : "<< SubEvSize <<std::endl;
486 // In principle, should be reset here for safety
487 fSubSubEvId = 0;
488 }
489 else {
490 // Skip all other subevents
491 offset += (4 + SubEvSize * 4);
492 }
493 }
494
495 offset = 16; // start from after the TRB event header again
496
497 // 2. Process TRB subsubevents
498
499 //Int_t iIter = 0;
500 while (static_cast<size_t>(offset) < size) {
502 if (fSkipMs == kTRUE) break;
503
504 //std::cout << "SE iteration " << iIter++ << "\toffset=" << offset << "\tsize=" << size << std::endl;
505
506 // We suppose that the fifth word is the header of the subevent
507 // <Length> <HubId>
508 mRichSupport::SwapBytes(4, ptr + offset);
509 // clang-format off
510 dataPtr = (Int_t*) (ptr + offset);
511 Int_t SubEvSize = (Int_t)((dataPtr[0] >> 16) & 0xffff);
512 Int_t HubId = (Int_t)((dataPtr[0]) & 0xffff);
513 // clang-format on
514 //FIXME change from 0xc001 to 0xc000 at some point // ?
515 if ((HubId == 0xc001) || (HubId == 0xc000)) {
522
523 // Skip CTS subevent as it has been already processed during the first run
524 offset += (4 + SubEvSize * 4);
525 fLastFeeOnHub = false;
526 }
527 else if (HubId == 0x5555) {
528 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
529 << "ok"
530 << "\t"
531 << "hub ID = 0x" << mRichSupport::GetHexRepresentation(2, ptr + offset) << "\t"
532 << "subevent size = " << SubEvSize;
533 fGwordCnt++;
534 fLastFeeOnHub = false;
535 //TODO one could implement additional checks here about the
536 // words coming after the "event end" but we skip everything by now.
538 offset += (4 + ProcessSKIPsubevent(SubEvSize * 4, ptr + offset)); //
540 }
541 else if (((HubId >> 8) & 0xFF) == 0x82) {
542 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
543 << "ok"
544 << "\t"
545 << "hub ID = 0x" << mRichSupport::GetHexRepresentation(2, ptr + offset) << "\t"
546 << "subevent size = " << SubEvSize;
547 fGwordCnt++;
548 fLastFeeOnHub = false;
549 //std::cout<<"Hub: "<<std::hex<<HubId <<std::dec<<" Size:"<< SubEvSize<<std::endl;
551 offset += (4 + ProcessTRBsubevent(SubEvSize * 4, ptr + offset)); //
553
554 //std::cout<<"Words in Hub 0x"<< std::hex << HubId << std::dec <<" : "<< SubEvSize <<std::endl;
555 // Bytes in a Hub
556 if (fbDebugMonitorMode) {
557 uint16_t combiner_address = ((HubId >> 4) & 0xF) * 3 + (HubId & 0xF);
558 fhSubEventSize->Fill(combiner_address, (SubEvSize * 4));
559 }
560 }
561 else {
562 LOG(warning) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
563 << "ok"
564 << "\t"
565 << "hub ID = 0x" << mRichSupport::GetHexRepresentation(2, ptr + offset) << "\t"
566 << "subevent size = " << SubEvSize << "\n"
567 << "This is not a valid Combiner Id!"
568 << "\n"
569 << "prev prev2:" << mRichSupport::GetWordHexRepr(ptr + offset - 12) << "\n"
570 << "prev prev: " << mRichSupport::GetWordHexRepr(ptr + offset - 8) << "\n"
571 << "prev: " << mRichSupport::GetWordHexRepr(ptr + offset - 4) << "\n"
572 << "next: " << mRichSupport::GetWordHexRepr(ptr + offset + 4) << "\n"
573 << "next next: " << mRichSupport::GetWordHexRepr(ptr + offset + 8) << "\n";
575 offset += (4 + SubEvSize * 4);
577 }
578 }
579
581 //TODO implement checks
582 if (size != static_cast<size_t>(offset)) {
583 LOG(warning) << "CbmMcbm2018UnpackerAlgoRich2020::ProcessTRBevent() warning:"
584 << "Number of processed bytes is not equal to the expected size. "
585 "This should not happen. ("
586 << size << " VS " << offset << ")";
587 }
588
589 return size; //TODO check
590}
591
592// Process TRB event header.
593// Input arguments are the size of the TRB event header (16 bytes) and the pointer to the first word.
594// Note that the first word can already be analysed outside of this method.
595// Return number of bytes processed. For this particular method the value of the input 'size' argument
596// is returned as we expect that the TRB header is always 16 bytes.
597Int_t CbmMcbm2018UnpackerAlgoRich2020::ProcessTRBeventHeader(size_t const size, uint8_t const* const ptr)
598{
599 Int_t offset; // offset in bytes
600 Int_t* dataPtr;
601
602 // Skip first word (already processed outside)
603 //offset = 0;
604 // do nothing
605
606 // We suppose that the second word consists of
607 // 0002 - number of following word till the Event Data Starts (should be the same)
608 // 00<TriggerType>1 - value in [7:4] defines TriggerType
609 offset = 4;
610 mRichSupport::SwapBytes(4, ptr + offset);
611 // clang-format off
612 dataPtr = (Int_t*) (ptr + offset);
613 Int_t checkSize = (Int_t)((dataPtr[0] >> 16) & 0xffff);
614 Int_t triggerType = (Int_t)((dataPtr[0] >> 4) & 0xf);
615 // clang-format on
616 if (checkSize == 2) {
617 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
618 << "ok"
619 << "\t"
620 << "checkSize == 2"
621 << "\t"
622 << "trigger type = " << triggerType;
623 fGwordCnt++;
624 }
625 else {
626 LOG(warning) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
627 << "er"
628 << "\t"
629 << "checkSize != 2 (" << checkSize << ")\t"
630 << "trigger type = " << triggerType;
631 fGwordCnt++;
632
634 fSkipMs = kTRUE;
635 return 0;
636 }
637
638 /*for (size_t iWord=2; iWord<size; iWord++) {
639 offset = iWord*4;
640 LOG(debug4) << "\t" << GetWordHexRepr(ptr+offset);
641 }*/
642
643 // We suppose that the third word consists of
644 // 0000 <SubEventId>
645 offset = 8;
646 mRichSupport::SwapBytes(4, ptr + offset);
647 // clang-format off
648 dataPtr = (Int_t*) (ptr + offset);
649 Int_t checkBytes = (Int_t)((dataPtr[0] >> 16) & 0xffff);
650 // clang-format on
651 // Int_t SubEvId = (Int_t)((dataPtr[0]) & 0xffff);
652 if (checkBytes == 0) {
653 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
654 << "ok"
655 << "\t"
656 << "checkBytes == 0"
657 << "\t"
658 << "subevent ID = 0x" << mRichSupport::GetHexRepresentation(2, ptr + offset);
659 fGwordCnt++;
660 }
661 else {
662 LOG(warning) << "[" << fGwordCnt++ << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
663 << "er"
664 << "\t"
665 << "checkBytes != 0 (" << checkBytes << ")\t"
666 << "subevent ID = 0x" << mRichSupport::GetHexRepresentation(2, ptr + offset);
667 fGwordCnt++;
668
670 fSkipMs = kTRUE;
671 return 0;
672 }
673
674 // We suppose that the fourth word is the trigger number
675 offset = 12;
676 mRichSupport::SwapBytes(4, ptr + offset);
677 // clang-format off
678 dataPtr = (Int_t*) (ptr + offset);
679 UInt_t TriggerNum = (UInt_t)(dataPtr[0]);
680 // clang-format on
681 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
682 << "ok"
683 << "\t"
684 << "trigger num = " << TriggerNum;
685 fGwordCnt++;
686
687 return size;
688}
689
690Int_t CbmMcbm2018UnpackerAlgoRich2020::ProcessSKIPsubevent(size_t const size, uint8_t const* const ptr)
691{
693
694 Int_t offset; // offset in bytes
695 Int_t* dataPtr; //(FU) not used
696 uint16_t SubEventError = 0;
697
698 // Skip first word (already processed outside)
699 offset = 4;
700
701 //Start Error identification
702 mRichSupport::SwapBytes(4, ptr + offset);
703 // clang-format off
704 dataPtr = (Int_t*) (ptr + offset);
705 SubEventError = (uint16_t)((dataPtr[0] >> 16) & 0xffff);
706 // clang-format on
707 ErrorMsg(static_cast<uint16_t>(SubEventError), RichErrorType::subEventError);
708
709 offset = 8;
710 //End Error identification
711
712 while (static_cast<size_t>(offset) < size + 4) {
713 mRichSupport::SwapBytes(4, ptr + offset);
714 // dataPtr = (Int_t*)(ptr+offset); (FU) not used
715 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset);
716 fGwordCnt++;
717
718 offset += 4;
719 }
720
722 //TODO implement checks
723 if (size != static_cast<size_t>(offset - 4)) {
724 LOG(warning) << "CbmMcbm2018UnpackerAlgoRich2020::ProcessSKIPsubevent() warning:"
725 << "Number of processed bytes is not equal to the expected size. "
726 "This should not happen.";
727 }
728
729 return size; //TODO check
730}
731
732Int_t CbmMcbm2018UnpackerAlgoRich2020::ProcessCTSsubevent(size_t const size, uint8_t const* const ptr)
733{
735
736 Int_t offset; // offset in bytes
737 Int_t* dataPtr;
738
739 // Skip first word (already processed outside)
740
741 // We suppose that the second word is the header of the subsubevent
742 offset = 4;
743 mRichSupport::SwapBytes(4, ptr + offset);
744 // clang-format off
745 dataPtr = (Int_t*) (ptr + offset);
746 // clang-format on
747 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
748 << "ok"
749 << "\t"
750 << "CTS header";
751 fGwordCnt++;
752
753 /* (FU) not used
754 Short_t trigState[16];
755 for (Int_t i=0; i<16; i++) {
756 trigState[i] = ((*dataPtr >> i) & 0x1); // 16 x 1 bit
757 }
758*/
759 Short_t nInp = ((*dataPtr >> 16) & 0xf); // 4 bits
760 Short_t nTrigCh = ((*dataPtr >> 20) & 0x1f); // 5 bits
761 Short_t inclLastIdle = ((*dataPtr >> 25) & 0x1); // 1 bit
762 Short_t inclTrigInfo = ((*dataPtr >> 26) & 0x1); // 1 bit
763 Short_t inclTS = ((*dataPtr >> 27) & 0x1); // 1 bit
764 Short_t ETM = ((*dataPtr >> 28) & 0x3); // 2 bits
765
766 // in words (not bytes)
767 Short_t CTSinfo_size = nInp * 2 + nTrigCh * 2 + inclLastIdle * 2 + inclTrigInfo * 3 + inclTS;
768 switch (ETM) {
769 case 0: break;
770 case 1: CTSinfo_size += 1; break;
771 case 2: CTSinfo_size += 4; break;
772 case 3:
773 LOG(debug) << "ETM == 3";
774 //TODO implement
775 break;
776 }
777
778 LOG(debug) << "CTS information size (extracted from the CTS header): " << CTSinfo_size;
779
780 offset = 8;
781
782 while (offset - 8 < CTSinfo_size * 4) {
783 mRichSupport::SwapBytes(4, ptr + offset);
784 // clang-format off
785 dataPtr = (Int_t*) (ptr + offset);
786 ULong_t MSidx = 102400UL * ((ULong_t)(*dataPtr) - 1);
787 // clang-format on
788 LOG(debug) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
789 << "ok"
790 << "\t"
791 << "CTS information"
792 << " MSidx=" << MSidx;
793 fGwordCnt++;
794
795 offset += 4;
796 }
797
798 // size - full size including CTS header word, CTS informations words (CTSinfo_size) and TCD data
799 // Thus TDC data size = full size - 1 word (header) - CTSinfo_size words (CTS informations)
801 fChnlMsgCnt.fill(0);
802 offset += (ProcessTRBsubsubevent((size - (1 + CTSinfo_size) * 4), ptr + offset, 0, 0)); //
804
806 //TODO implement checks
807 if (size != static_cast<size_t>(offset - 4)) {
808 LOG(warning) << "CbmMcbm2018UnpackerAlgoRich2020::ProcessCTSsubevent() warning:"
809 << "Number of processed bytes is not equal to the expected size. "
810 "This should not happen.";
811 }
812
813 return size; //TODO check
814}
815
816Int_t CbmMcbm2018UnpackerAlgoRich2020::ProcessTRBsubevent(size_t const size, uint8_t const* const ptr)
817{
819
820 Int_t offset; // offset in bytes
821 Int_t* dataPtr;
822
823 // Skip first word (already processed outside)
824 offset = 4;
825
827
829
830 //Int_t iIter = 0;
831 while (static_cast<size_t>(offset) < (size - 2)) { // test for cases with odd number of corrections
832 if (fSkipMs == kTRUE) break;
833 //std::cout << "SSE iteration " << iIter++ << "\toffset=" << offset << "\tsize=" << size << std::endl;
834
835 //correct for misalignment
836 if (fTDCAlignmentErrorPositions.size() > static_cast<unsigned int>(fTdcWordCorrectionCnt)
838 //std::cout<<"Correction in DiRICH Header: "<< fTDCAlignmentErrorPositions[fTdcWordCorrectionCnt]<<std::endl;
839 offset += 2;
841 }
842
843 // We suppose that the second word is the header of the subsubevent
844 // <Length> <SubSubEv.Id>
845 mRichSupport::SwapBytes(4, ptr + offset);
846 // clang-format off
847 dataPtr = (Int_t*) (ptr + offset);
848 Int_t SubSubEvSize = (Int_t)((dataPtr[0] >> 16) & 0xffff);
849 fSubSubEvId = (Int_t)((dataPtr[0]) & 0xffff);
850 // clang-format on
851 //check if it is the last DiRICH in the Hub Data stream
852 //TODO CHECK!
853 if ((static_cast<size_t>(offset) + SubSubEvSize * 4) >= size) {
854 LOG(debug) << "Last DiRICH on HUB";
855 fLastFeeOnHub = true;
856 }
857
858 if (((fSubSubEvId >> 12) & 0xF) != 0x7) {
859 LOG(error) << mRichSupport::GetWordHexRepr(ptr + offset - 12) << "\t"
860 << "er"
861 << "\t"
862 << "ILLEGAL SubSubEvent Id prev";
863 LOG(error) << mRichSupport::GetWordHexRepr(ptr + offset - 8) << "\t"
864 << "er"
865 << "\t"
866 << "ILLEGAL SubSubEvent Id prev";
867 LOG(error) << mRichSupport::GetWordHexRepr(ptr + offset - 4) << "\t"
868 << "er"
869 << "\t"
870 << "ILLEGAL SubSubEvent Id prev";
871 LOG(error) << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
872 << "er"
873 << "\t"
874 << "ILLEGAL SubSubEvent Id "
875 << "Offset:" << static_cast<size_t>(offset) << " Size:" << size;
876 LOG(error) << mRichSupport::GetWordHexRepr(ptr + offset + 4) << "\t"
877 << "er"
878 << "\t"
879 << "ILLEGAL SubSubEvent Id next";
880 LOG(error) << mRichSupport::GetWordHexRepr(ptr + offset + 8) << "\t"
881 << "er"
882 << "\t"
883 << "ILLEGAL SubSubEvent Id next";
884 LOG(error) << mRichSupport::GetWordHexRepr(ptr + offset + 12) << "\t"
885 << "er"
886 << "\t"
887 << "ILLEGAL SubSubEvent Id next";
888 }
889
890 LOG(debug) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr + offset) << "\t"
891 << "ok"
892 << "\t"
893 << "subsubevent ID (FPGA ID) = 0x" << mRichSupport::GetHexRepresentation(2, ptr + offset) << "\t"
894 << "subsubevent size = " << SubSubEvSize << " | HUB Offset:" << static_cast<size_t>(offset)
895 << " Size:" << size;
896 fGwordCnt++;
897
898 if (size + 4 < static_cast<size_t>(offset + 4 + SubSubEvSize * 4 - fTdcWordCorrectionCnt * 2)) {
899 LOG(warning) << "CbmMcbm2018UnpackerAlgoRich2020::ProcessTRBsubevent() warning:"
900 << "SubEvent out of bounds. This should not happen. (" << size << " VS "
901 << (offset + 4 + SubSubEvSize * 4 - fTdcWordCorrectionCnt * 2) << ")";
902
904 //fSkipMs = kTRUE;
905 }
906
907 fChnlMsgCnt.fill(0);
908
909 // Add 4 bytes which correspond to the header word
911 offset += (4 + ProcessTRBsubsubevent(SubSubEvSize * 4, ptr + offset + 4, offset + 4, size)); //
913
914 //std::cout<<"Words in DiRICH 0x"<< std::hex << fSubSubEvId << std::dec <<" : "<< SubSubEvSize <<std::endl;
915
916 if (fbDebugMonitorMode) {
917 //This address calculation is just for mCBM; will be a problem when using full CBM RICH acceptance
918 uint16_t DiRICH_address = ((fSubSubEvId >> 8) & 0xF) * 18 + ((fSubSubEvId >> 4) & 0xF) * 2 + (fSubSubEvId & 0xF);
919 fhSubSubEventSize->Fill(DiRICH_address,
920 SubSubEvSize); // Words in a DiRICH
921
922 //Words per channel
923 for (size_t i = 1; i < fChnlMsgCnt.size(); ++i) {
924 if (fChnlMsgCnt.at(i) > 0) fhChnlSize->Fill(static_cast<int>(i), fChnlMsgCnt.at(i));
925 }
926 }
927
928 // In principle, should be reset here for safety
929 fSubSubEvId = 0;
930 }
931
932 if (static_cast<Int_t>(fTDCAlignmentErrorPositions.size()) != fTdcWordCorrectionCnt)
933 std::cout << "Missing Correction" << std::endl;
934
935 // if (fTDCAlignmentErrorPositions.size() > 0){
936 // std::cout<<"Offset : "<<offset-4<<" Size:"<< size <<std::endl;
937 // std::cout<<"END of Hub : "<<mRichSupport::GetWordHexRepr(ptr+offset-4)<<std::endl; // Last word, processed as TDCWord
938 // std::cout<<"END of Hub +1 : "<<mRichSupport::GetWordHexRepr(ptr+offset+0)<<std::endl;
939 // std::cout<<"END of Hub +2 : "<<mRichSupport::GetWordHexRepr(ptr+offset+4)<<std::endl;
940 // std::cout<<"END of Hub +3 : "<<mRichSupport::GetWordHexRepr(ptr+offset+8)<<std::endl;
941 // }
942
944 if (size != static_cast<size_t>(offset - 4)) {
945 LOG(warning) << "CbmMcbm2018UnpackerAlgoRich2020::ProcessTRBsubevent() warning:"
946 << "Number of processed bytes is not equal to the expected size. "
947 "This should not happen. ("
948 << size << " VS " << (offset - 4) << ")"
949 << " Correction: " << fTdcWordCorrectionCnt * 2 << " fLastFeeOnHub:" << fLastFeeOnHub;
950
952 //fSkipMs = kTRUE;
953 }
954
956
957 return size; //TODO check
958}
959
960Int_t CbmMcbm2018UnpackerAlgoRich2020::ProcessTRBsubsubevent(size_t const size, uint8_t const* const ptr,
961 Int_t const hubOffset, size_t const hubSize)
962{ //size: Size of Data from DiRICH in Bytes
964 Int_t offset = 0; // offset in bytes
965 fCurEpochCounter = 0; //TODO check
966 fInSubSubEvent = kFALSE; //TODO check
968 Int_t TdcWordCorrection_local = 0;
969 Int_t WordCnt = 0;
970 bool break_flag = false;
971
972 for (size_t iWord = 0; iWord < size / 4; iWord++) { // iWord is size in Lines
973 //correct for misalignment
974 //hubOffset is pointing to first word after DiRICH address
975 if (fTDCAlignmentErrorPositions.size() > static_cast<unsigned int>(fTdcWordCorrectionCnt)
976 && fTDCAlignmentErrorPositions[fTdcWordCorrectionCnt] == static_cast<Int_t>(hubOffset + offset + iWord * 4)) {
977 //BEGIN DEBUG
978 // std::cout<<"DEBUG -1: "<< mRichSupport::GetWordHexRepr(ptr-hubOffset+fTDCAlignmentErrorPositions[fTdcWordCorrectionCnt]-4) << std::endl;
979 // std::cout<<"DEBUG 0: "<< mRichSupport::GetWordHexRepr(ptr-hubOffset+fTDCAlignmentErrorPositions[fTdcWordCorrectionCnt]) << std::endl;
980 // std::cout<<"DEBUG +1: "<< mRichSupport::GetWordHexRepr(ptr-hubOffset+fTDCAlignmentErrorPositions[fTdcWordCorrectionCnt]+4) << std::endl;
981 // std::cout<<"DEBUG_ : "<< mRichSupport::GetWordHexRepr(ptr+iWord*4+offset) << std::endl;
982 //
983 // std::cout<<"Correction in DiRICH Header: "<< fTDCAlignmentErrorPositions[fTdcWordCorrectionCnt]<<std::endl;
984
985 //END DEBUG
986 offset += 2;
988 TdcWordCorrection_local++;
989 // repeat word
990 iWord--;
991 continue;
992 }
993 if (fSkipMs == kTRUE) break;
994
995
996 //if (fTDCAlignmentErrorPositions.size() > 0 && fLastFeeOnHub) std::cout<<"Final Word: "<< mRichSupport::GetWordHexRepr(ptr+iWord*4+offset)<<std::endl;
997
999 if ((hubSize > 0) && (hubOffset + offset + iWord * 4 > hubSize)) {
1000 //std::cout<<"BREAKING : "<<hubOffset+offset+iWord*4 <<" > "<< hubSize <<" | "<< offset << " | "<< fTdcWordCorrectionCnt <<std::endl;
1001 break_flag = true;
1002 break;
1003 }
1004 //if (isCTSWord) std::cout<<"TDCWORD: "<<mRichSupport::GetWordHexRepr(ptr+iWord*4+offset)<<std::endl;
1005
1006 mRichSupport::SwapBytes(4, ptr + iWord * 4 + offset);
1007 ProcessTDCword(ptr + iWord * 4 + offset, iWord, size); //
1008
1009 WordCnt++;
1010
1011 //std::cout<<" "<< iWord <<" "<< WordCnt <<std::endl;
1012 } //END of for Loop
1013
1014 // if (fTdcWordCorrectionCnt > 0){
1015 // std::cout<<"LAST Processed Word : "<<mRichSupport::GetWordHexRepr(ptr+(WordCnt-1)*4+offset)<<std::endl;
1016 // }
1017 //if (TdcWordCorrection_local != 0) printf(" --- TDC WORD FIX APPLIED ! --- [DiRICH : 0x%4x]\n",fSubSubEvId);
1018
1019 if (fSkipMs == kTRUE) return 0;
1020
1021 //TODO Implement checks that the first word was the header and the last word was the trailer
1022
1023 //if (size != static_cast<size_t>((WordCnt)*4) && fTdcWordCorrectionCnt == 0) {
1024 if (!((!break_flag && ((size) == static_cast<size_t>((WordCnt) *4)))
1025 || (break_flag && ((size - (fTdcWordCorrectionCnt * 2)) == static_cast<size_t>((WordCnt) *4))))) {
1026 LOG(warning) << "CbmMcbm2018UnpackerAlgoRich2020::ProcessTRBsubsubevent() warning:"
1027 << "Number of processed bytes is not equal to the expected size. "
1028 "This should not happen."
1029 << static_cast<size_t>(WordCnt * 4) << " " << size;
1031 //fSkipMs = kTRUE;
1032 }
1033
1034
1035 return (WordCnt * 4 + offset); //TODO check
1036}
1037
1038Int_t CbmMcbm2018UnpackerAlgoRich2020::ProcessTDCword(uint8_t const* const ptr, Int_t const word, size_t const size)
1039{
1040 // clang-format off
1041 Int_t* tdcDataPtr = (Int_t*) ptr;
1042 Int_t tdcData = tdcDataPtr[0];
1043 Int_t tdcTimeDataMarker = (tdcData >> 31) & 0x1; // 1 bit
1044 // clang-format on
1045
1046 bool errorInData = false;
1047
1048 // A TDC Time i only valid after a EPOCH or another TDC value
1049 if ((tdcTimeDataMarker == 0x1 && fTrbState == TrbNetState::TDC)
1050 || (tdcTimeDataMarker == 0x1 && fTrbState == TrbNetState::EPOCH)) {
1051 UInt_t tdcMarker = (tdcData >> 29) & 0x7; // 3 bits
1052 if (tdcMarker == 0x4 || tdcMarker == 0x5) {
1053 fDebugPrint = 0;
1055 ProcessTimestampWord(tdcData); //
1058 }
1059 else {
1060 std::cout << "wrong TDC Word!!" << std::endl;
1061 errorInData = true;
1062 }
1063 }
1064 else {
1065 UInt_t tdcMarker = (tdcData >> 29) & 0x7; // 3 bits
1066
1067 if (tdcMarker == 0x0) { // TDC trailer
1068 if (fInSubSubEvent) {
1070 LOG(error) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr) << "\t"
1071 << "er"
1072 << "\t"
1073 << "ILLEGAL TRAILER Position";
1074 errorInData = true;
1075 }
1076 else if ((size / 4 - static_cast<size_t>(word)) > 1) {
1077 //Trailer only at end of SubSubEvent!
1078 LOG(error) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr) << "\t"
1079 << "er"
1080 << "\t"
1081 << "Trailer only at end of SubSubEvent!" << size / 4 << " " << static_cast<size_t>(word);
1082 errorInData = true;
1083 }
1084 else {
1086
1087 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr) << "\t"
1088 << "ok"
1089 << "\t"
1090 << "TDC TRAILER";
1091 //extract TDC Trailer Error
1092 uint16_t errorBits = (tdcData) &0xffff; //16 bits
1094 fInSubSubEvent = kFALSE; // go out of InSubSubEvent state
1095 //fGwordCnt++;
1096 fDebugPrint = 0;
1097 }
1098 }
1099 else {
1100 LOG(info) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr) << "\t"
1101 << "er"
1102 << "\t"
1103 << "UNKNOWN (TDC TRAILER not after header)";
1104 //fSkipMs = kTRUE;
1105 errorInData = true;
1106 //exit(EXIT_FAILURE); //TODO probably one should get rid of explicit EXIT calls not to ruin unpacking of other detectors?
1107 }
1108 }
1109 else if (tdcMarker == 0x1) { // TDC header
1110 // UInt_t randomCode = (tdcData >> 16) & 0xff; // 8 bits
1111 // UInt_t errorBits = (tdcData) & 0xffff; //16 bits
1112 if (!fInSubSubEvent) {
1113 fInSubSubEvent = kTRUE; // go into InSubSubEvent state
1114
1116 LOG(error) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr) << "\t"
1117 << "er"
1118 << "\t"
1119 << "ILLEGAL HEADER Position";
1120 errorInData = true;
1121 }
1122 else if (!((((tdcData >> 8) & 0xFFFFFF) == 0x200096) || (((tdcData >> 8) & 0xFFFFFF) == 0x200095))) {
1123 LOG(error) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr) << "\t"
1124 << "er"
1125 << "\t"
1126 << "ILLEGAL HEADER Value";
1127 errorInData = true;
1128 }
1129 else {
1131 //extract TDC Header Error
1132 uint8_t errorBits = (tdcData) &0xff; //8 bits
1134 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr) << "\t"
1135 << "ok"
1136 << "\t"
1137 << "TDC HEADER";
1138 }
1139 //fGwordCnt++;
1140 }
1141 else {
1142 LOG(info) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr) << "\t"
1143 << "er"
1144 << "\t"
1145 << "UNKNOWN (TDC HEADER not after trailer)";
1146 errorInData = true;
1147 //fGwordCnt++;
1148 //fSkipMs = kTRUE;
1149 //exit(EXIT_FAILURE); //TODO probably one should get rid of explicit EXIT calls not to ruin unpacking of other detectors?
1150 }
1151 }
1152 else if (tdcMarker == 0x2) { // DEBUG
1153 // UInt_t debugMode = (tdcData >> 24) & 0x1f; // 5 bits
1154 // UInt_t debugBits = (tdcData) & 0xffffff; // 24 bits
1155 //fTrbState = TrbNetState::DEBUG;
1156 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr) << "\t"
1157 << "ok"
1158 << "\t"
1159 << "DEBUG";
1160 LOG(info) << "DEBUG VALUE [" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr);
1161 errorInData = true;
1162 //fGwordCnt++;
1163 // currently no actions if a DEBUG message is encountered.
1164 }
1165 else if (tdcMarker == 0x3) { // EPOCH counter
1167 LOG(error) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr) << "\t"
1168 << "er"
1169 << "\t"
1170 << "ILLEGAL EPOCH Position!";
1171 errorInData = true;
1172 }
1173 else if (((tdcData >> 28) & 0xF) != 0x6) { //EPOCH is always 0x6....
1174 LOG(error) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr) << "\t"
1175 << "er"
1176 << "\t"
1177 << "ILLEGAL EPOCH value :";
1178 errorInData = true;
1179 }
1180 else {
1182 fDebugPrint = 0;
1183 fCurEpochCounter = (tdcData) &0xfffffff; // 28 bits
1184 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr) << "\t"
1185 << "ok"
1186 << "\t"
1187 << "EPOCH\t" << fCurEpochCounter;
1188 //fGwordCnt++;
1189 }
1190 }
1191 else {
1192 if (tdcTimeDataMarker != 0x1) {
1193 LOG(error) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr(ptr) << "\t"
1194 << "er"
1195 << "\t"
1196 << "UNKNOWN";
1197 errorInData = true;
1198 }
1199 }
1200 }
1201
1202 if (errorInData) {
1203 //Handle error
1204 fSkipMs = kTRUE;
1205 fSkipCnt++;
1206 LOG(error) << " >>> Skipping MicroTS due to error in data! <<<";
1207 }
1208
1209
1210 return 0; //correction;
1211}
1212
1214{
1215 Int_t channel = (tdcData >> 22) & 0x7f; // 7 bits
1216 Int_t fine = (tdcData >> 12) & 0x3ff; // 10 bits
1217 Int_t edge = (tdcData >> 11) & 0x1; // 1 bit
1218 Int_t coarse = (tdcData) &0x7ff; // 11 bits
1219 Int_t epoch = fCurEpochCounter;
1220
1221 //TODO move full time calculation outside
1222 // clang-format off
1223 Double_t fullTime = (Double_t) epoch * 2048. * 5. + (Double_t) (coarse) *5. - (Double_t) (fine) *0.005;
1224 // clang-format on
1225
1226 LOG(debug4) << "[" << fGwordCnt << "]\t" << mRichSupport::GetWordHexRepr((uint8_t*) &tdcData) << "\t"
1227 << "ok"
1228 << "\t"
1229 << "TIMESTAMP"
1230 << "\t"
1231 << "ch=" << channel << "\t"
1232 << "edge=" << edge << "\t"
1233 << "epoch=" << epoch << "\t"
1234 << "coarse=" << coarse << "\t"
1235 << "fine=" << fine << "\t"
1236 << "full=" << fullTime;
1237 //fGwordCnt++;
1238
1239 // Storing reference times
1240 // =======================
1241
1243 Int_t idx = fUnpackPar->GetAddressIdx(fSubSubEvId);
1244 if (-1 == idx) {
1246 fSkipMs = kTRUE;
1247 return;
1248 }
1250
1251 if ((fSubSubEvId == 0xc000) || (fSubSubEvId == 0xc001)) {
1252 // if CTS
1253 if ((channel == 0) && (edge == RISINGEDGEID)) {
1255 fLastCTSch0_re_time = fullTime;
1257 }
1258 else if ((channel == 2) && (edge == RISINGEDGEID)) {
1260 fLastCTSch2_re_time = fullTime;
1262 }
1263 else if ((channel == 2) && (edge == FALLINGEDGEID)) {
1265 fLastCTSch2_fe_time = fullTime;
1267 }
1268 }
1269 else {
1270 // if not CTS (which means TRB)
1271 if ((channel == 0) && (edge == RISINGEDGEID)) {
1273 fLastCh0_re_time[idx] = fullTime;
1275 }
1276 }
1277
1278 // Calculation of corrected time
1279 // =============================
1280 Double_t fullTimeCorr = 0.;
1281 if (!((fSubSubEvId == 0xc000) || (fSubSubEvId == 0xc001))) {
1282 if (channel != 0) {
1283 Double_t dT = fullTime - fPrevLastCh0_re_time[idx];
1285 fullTimeCorr = dT - corr;
1286 }
1287 }
1288
1289 // Filling histograms
1290 // ==================
1291 if (fbMonitorMode == kTRUE) {
1292 if (!((fSubSubEvId == 0xc000) || (fSubSubEvId == 0xc001))) {
1293 // if not CTS (which means TRB)
1294 if ((channel == 0) && (edge == RISINGEDGEID)) {
1295 /* Double_t dT1 = fullTime - fLastCTSch0_re_time;
1296 Double_t dT2 = fullTime - fLastCTSch2_re_time;
1297 Double_t dT3 = fullTime - fLastCTSch2_fe_time;
1298 fhTDCch0re_minusCTSch0re->Fill(idx, dT1);
1299 fhTDCch0re_minusCTSch2re->Fill(idx, dT2);
1300 fhTDCch0re_minusCTSch2fe->Fill(idx, dT3);
1301
1302 Double_t dT4 = fullTime - fPrevLastCTSch0_re_time;
1303 Double_t dT5 = fullTime - fPrevLastCTSch2_re_time;
1304 Double_t dT6 = fullTime - fPrevLastCTSch2_fe_time;
1305 fhTDCch0re_minusPrevCTSch0re->Fill(idx, dT4);
1306 fhTDCch0re_minusPrevCTSch2re->Fill(idx, dT5);
1307 fhTDCch0re_minusPrevCTSch2fe->Fill(idx, dT6);
1308
1309 LOG(debug4) << "dT1=" << dT1 << "\tdT2=" << dT2 << "\tdT3=" << dT3
1310 << "\tdT4=" << dT4 << "\tdT5=" << dT5 << "\tdT6=" << dT6;
1311*/
1312 }
1313
1314 if ((channel != 0) && (edge == RISINGEDGEID)) {
1315 /*Double_t dT7 = fullTime - fLastCh0_re_time[idx];
1316 TH2D* h1 = fhTDCre_minusTDCch0re.at(idx);
1317 h1->Fill(channel, dT7);*/
1318
1319 Double_t dT8 = fullTime - fPrevLastCh0_re_time[idx];
1320 /*TH2D* h2 = fhTDCre_minusPrevTDCch0re.at(idx);
1321 h2->Fill(channel, dT8);*/
1322
1324 Double_t correctedT1 = dT8 + corr1;
1325 Double_t correctedT2 = dT8 - corr1;
1326 /*
1327// TH2D* h3 = fhTDCre_corrected1.at(idx);
1328// h3->Fill(channel, correctedT1);
1329// TH2D* h4 = fhTDCre_corrected2.at(idx);
1330// h4->Fill(channel, correctedT2);
1331*/
1332 LOG(debug4)
1333 /*<< "dT7=" << dT7*/ << "\tdT8=" << dT8 << "\tcorr1=" << corr1 << "\tcorrectedT1=" << correctedT1
1334 << "\tcorrectedT2=" << correctedT2;
1335 }
1336 }
1337 }
1338
1339 if (edge == RISINGEDGEID) { this->ProcessRisingEdge(fSubSubEvId, channel, fullTimeCorr); }
1340 else {
1341 this->ProcessFallingEdge(fSubSubEvId, channel, fullTimeCorr);
1342 }
1343
1344 fChnlMsgCnt.at(channel)++;
1345 if (fTrbState == TrbNetState::EPOCH) fChnlMsgCnt.at(channel)++; // If there was a correp. EPOCH before
1346}
1347
1348void CbmMcbm2018UnpackerAlgoRich2020::ProcessRisingEdge(Int_t subSubEvId, Int_t channel, Double_t time)
1349{
1351
1352 //TODO: not a very nice hack.
1353 // All messages from ch0 are skipped. Though, probably, that is corect.
1354 if (channel == 0) return;
1355
1356 // Also skip everything from CST
1357 if ((subSubEvId == 0xc000) || (subSubEvId == 0xc001)) return;
1358
1359 fRisingEdgesBuf.push_back(CbmMcbmRichEdge(subSubEvId, channel, time));
1360}
1361
1362void CbmMcbm2018UnpackerAlgoRich2020::ProcessFallingEdge(Int_t subSubEvId, Int_t channel, Double_t time)
1363{
1365
1366 // Skip everything from CST
1367 if ((subSubEvId == 0xc000) || (subSubEvId == 0xc001)) return;
1368
1369 Bool_t reFound = kFALSE;
1370
1371 std::vector<CbmMcbmRichEdge>::iterator reIter = fRisingEdgesBuf.begin();
1372
1373 while (reIter != fRisingEdgesBuf.end()) {
1374 if (((*reIter).fSubSubEventID == subSubEvId) && ((*reIter).fChannel == channel)) {
1375 Double_t reTime = (*reIter).fTime;
1376 // Found corresponding rising edge
1377 Double_t ToT = time - reTime;
1378
1379 if ((ToT >= TOTMIN) && (ToT <= TOTMAX)) {
1380 // Time-over-threshold is within allowed range
1381
1382 reFound = kTRUE;
1383
1384 LOG(debug4) << "Found pair for FPGA ID 0x" << std::hex << subSubEvId << std::dec << "\tch=" << channel
1385 << "\tToT=" << ToT;
1386
1387 //TODO implement
1388 // Writing output digi
1390 if (fbMonitorMode) {
1391 TH1D* h = GetTotH1(subSubEvId, channel);
1392 if (h != nullptr) h->Fill(ToT);
1393
1394 TH2D* h2 = GetTotH2(subSubEvId);
1395 if (h2 != nullptr) h2->Fill(channel, ToT);
1396 }
1397 WriteOutputDigi(subSubEvId, channel, reTime, ToT, fCurMSidx); //
1399
1400 reIter = fRisingEdgesBuf.erase(reIter);
1401 continue; // Take care. This has to be the last operation in this block
1402 }
1403 else {
1404 //TODO: exception. By now we can just do nothing
1405 }
1406 } // end of if condition
1407
1408 // This construction is a little bit tricky.
1409 // The iterator is either incremented here or (if a pair was found)
1410 // incremented using erase call, followed by the continue.
1411 ++reIter;
1412 } // end of for loop
1413
1414 if (reFound == kFALSE) {
1415 // Corresponding rising edge not found - store the falling edge in the bufer
1416 fFallingEdgesBuf.push_back(CbmMcbmRichEdge(subSubEvId, channel, time));
1417 }
1418}
1419
1420void CbmMcbm2018UnpackerAlgoRich2020::WriteOutputDigi(Int_t fpgaID, Int_t channel, Double_t time, Double_t tot,
1421 uint64_t MSidx)
1422{
1423 Double_t ToTcorr = fbDoToTCorr ? fUnpackPar->GetToTshift(fpgaID, channel) : 0.;
1424 Int_t pixelUID = this->GetPixelUID(fpgaID, channel);
1425 //check ordering
1426 Double_t finalTime = time + (Double_t) MSidx - fdTimeOffsetNs;
1427
1428 Double_t lastTime = 0.;
1429
1430 if (fDigiVect.size() < 1) { fDigiVect.emplace_back(pixelUID, finalTime, tot - ToTcorr); }
1431 else {
1432 lastTime = fDigiVect[fDigiVect.size() - 1].GetTime();
1433 if (lastTime > finalTime) {
1434 for (int i = fDigiVect.size() - 1; i >= 0; i--) {
1435 lastTime = fDigiVect[i].GetTime();
1436 if (lastTime <= finalTime) {
1437 // LOG(info) << " before:"<< fDigiVect.size();
1438 fDigiVect.emplace(fDigiVect.begin() + i + 1, pixelUID, finalTime, tot - ToTcorr);
1439 // LOG(info) << fDigiVect.size();
1440 break;
1441 }
1442 }
1443 }
1444 else {
1445 fDigiVect.emplace_back(pixelUID, finalTime, tot - ToTcorr);
1446 }
1447 }
1448 LOG(debug4) << "CbmMcbm2018UnpackerAlgoRich2020::WriteOutputDigi fDigiVect.size=" << fDigiVect.size();
1449}
1450
1452{
1453 // for (int i = 0; i < fDigiVect.size();++i) {
1454 // LOG(info) << "CbmMcbm2018UnpackerAlgoRich2020::Final Vector: "
1455 // << i+1 <<"/"<<fDigiVect.size()
1456 // << "\t" << std::setprecision(15)<< fDigiVect[i].GetTime();
1457 //
1458 //
1459 // }
1460 LOG(debug4) << "CbmMcbm2018UnpackerAlgoRich2020::FinalizeTs: " << fRisingEdgesBuf.size()
1461 << " entries in fRisingEdgesBuf"
1462 << "\t" << fFallingEdgesBuf.size() << " entries in fFallingEdgesBuf";
1463
1464 // Clear rising edges buffer
1465 LOG(debug4) << "Rising edges: "
1466 "----------------------------------------------------------";
1467 std::vector<CbmMcbmRichEdge>::iterator reIter = fRisingEdgesBuf.begin();
1468 while (reIter != fRisingEdgesBuf.end()) {
1469 LOG(debug4) << "FPGA=0x" << std::hex << (*reIter).fSubSubEventID << std::dec << "\tch=" << (*reIter).fChannel;
1470 ++reIter;
1471 }
1472 fRisingEdgesBuf.clear();
1473
1474 // Clear falling edges buffer
1475 LOG(debug4) << "Falling edges: "
1476 "---------------------------------------------------------";
1477 std::vector<CbmMcbmRichEdge>::iterator feIter = fFallingEdgesBuf.begin();
1478 while (feIter != fFallingEdgesBuf.end()) {
1479 LOG(debug4) << "FPGA=0x" << std::hex << (*feIter).fSubSubEventID << std::dec << "\tch=" << (*feIter).fChannel;
1480 ++feIter;
1481 }
1482 fFallingEdgesBuf.clear();
1483
1484 LOG(debug4) << "---------------------------------------------------------";
1485}
1486
1488{
1489 Int_t nTDCs = fUnpackPar->GetNaddresses();
1490 // std::vector<TCanvas*> fcToT2d;
1491 /*
1492 fhTDCch0re_minusCTSch0re = new TH2D("fhTDCch0re_minusCTSch0re", "TDC ch0 re - CTS ch0 re;TDC index;ns", nTDCs, 0, nTDCs, 1000, -500., 500.);
1493 fhTDCch0re_minusCTSch2re = new TH2D("fhTDCch0re_minusCTSch2re", "TDC ch0 re - CTS ch2 re;TDC index;ns", nTDCs, 0, nTDCs, 1000, -500., 500.);
1494 fhTDCch0re_minusCTSch2fe = new TH2D("fhTDCch0re_minusCTSch2fe", "TDC ch0 re - CTS ch2 fe;TDC index;ns", nTDCs, 0, nTDCs, 1000, -500., 500.);
1495
1496 AddHistoToVector(fhTDCch0re_minusCTSch0re, "");
1497 AddHistoToVector(fhTDCch0re_minusCTSch2re, "");
1498 AddHistoToVector(fhTDCch0re_minusCTSch2fe, "");
1499
1500 fhTDCch0re_minusPrevCTSch0re = new TH2D("fhTDCch0re_minusPrevCTSch0re", "TDC ch0 re - prev CTS ch0 re;TDC index;ns", nTDCs, 0, nTDCs, 1000, -500., 500.);
1501 fhTDCch0re_minusPrevCTSch2re = new TH2D("fhTDCch0re_minusPrevCTSch2re", "TDC ch0 re - prev CTS ch2 re;TDC index;ns", nTDCs, 0, nTDCs, 1000, -500., 500.);
1502 fhTDCch0re_minusPrevCTSch2fe = new TH2D("fhTDCch0re_minusPrevCTSch2fe", "TDC ch0 re - prev CTS ch2 fe;TDC index;ns", nTDCs, 0, nTDCs, 1000, -500., 500.);
1503
1504 AddHistoToVector(fhTDCch0re_minusPrevCTSch0re, "");
1505 AddHistoToVector(fhTDCch0re_minusPrevCTSch2re, "");
1506 AddHistoToVector(fhTDCch0re_minusPrevCTSch2fe, "");
1507*/
1508
1509 fhTdcErrors = new TH2D("fhTdcErrors", "Errors in TDC msgs;;", nTDCs, -0.5, nTDCs - 0.5, 9, -0.5, 8.5);
1510 fhTdcErrors->GetYaxis()->SetBinLabel(1, "RingBuffOverw.");
1511 fhTdcErrors->GetYaxis()->SetBinLabel(2, "noRefTime");
1512 fhTdcErrors->GetYaxis()->SetBinLabel(3, "refTimePrecedes");
1513 fhTdcErrors->GetYaxis()->SetBinLabel(4, "trigW/oRefTime");
1514 fhTdcErrors->GetYaxis()->SetBinLabel(5, "markMisRefTime");
1515 fhTdcErrors->GetYaxis()->SetBinLabel(6, "multiRefTime");
1516 fhTdcErrors->GetYaxis()->SetBinLabel(7, "refTime<40ns");
1517 fhTdcErrors->GetYaxis()->SetBinLabel(8, "noValidation");
1518 fhTdcErrors->GetYaxis()->SetBinLabel(9, "trigger!=0x1");
1519 fhTdcErrors->GetXaxis()->LabelsOption("v");
1520 fhTdcErrors->GetYaxis()->SetTickSize(0.0);
1521 fhTdcErrors->GetXaxis()->SetTickSize(0.0);
1522 //fhTdcErrors->SetGrid();
1523
1524 fhEventErrors = new TH2D("fhEventErrors", "Errors in Event/mts msgs;;", 1, -0.5, 0.5, 13, -0.5, 12.5);
1525 fhEventErrors->GetYaxis()->SetBinLabel(1, "UDPProblem");
1526 fhEventErrors->GetYaxis()->SetBinLabel(2, "evNumMism");
1527 fhEventErrors->GetYaxis()->SetBinLabel(3, "trigMism");
1528 fhEventErrors->GetYaxis()->SetBinLabel(4, "wrongLength");
1529 fhEventErrors->GetYaxis()->SetBinLabel(5, "answMissing");
1530 fhEventErrors->GetYaxis()->SetBinLabel(6, "evRequFail");
1531 fhEventErrors->GetYaxis()->SetBinLabel(7, "evPartFound");
1532 fhEventErrors->GetYaxis()->SetBinLabel(8, "sevBuffProb");
1533 fhEventErrors->GetYaxis()->SetBinLabel(9, "brokenEv");
1534 fhEventErrors->GetYaxis()->SetBinLabel(10, "ethLinkDwn");
1535 fhEventErrors->GetYaxis()->SetBinLabel(11, "subEvBuffAlmFull");
1536 fhEventErrors->GetYaxis()->SetBinLabel(12, "eth/BufProb");
1537 fhEventErrors->GetYaxis()->SetBinLabel(13, "timingTrigErr");
1538 fhEventErrors->GetXaxis()->LabelsOption("v");
1539 fhEventErrors->GetXaxis()->SetTickSize(0.0);
1540 fhEventErrors->GetYaxis()->SetTickSize(0.0);
1541
1542 for (Int_t iTDC = 0; iTDC < nTDCs; iTDC++) {
1543 TString histoName;
1544 TString histoTitle;
1545 TString subFolder;
1546
1547 Int_t Addr = fUnpackPar->GetAddress(iTDC);
1548 fMapFEE[Addr] = iTDC;
1549 fhTdcErrors->GetXaxis()->SetBinLabel(iTDC + 1, Form("0x%4x", Addr));
1550 /*
1551 histoName.Form("fhTDC%dre_minusTDC%dch0re", iTDC, iTDC);
1552 histoTitle.Form("TDC %d re - TDC %d ch0 re;channel;ns", iTDC, iTDC);
1553 TH2D* h1 = new TH2D(histoName, histoTitle, 32, 0., 32., 1200, 0., 600.);
1554 fhTDCre_minusTDCch0re.push_back(h1);
1555 AddHistoToVector(h1);
1556
1557 histoName.Form("fhTDC%dre_minusPrevTDC%dch0re", iTDC, iTDC);
1558 histoTitle.Form("TDC %d re - prev. TDC %d ch0 re;channel;ns", iTDC, iTDC);
1559 TH2D* h2 = new TH2D(histoName, histoTitle, 32, 0., 32., 1200, 0., 600.);
1560 fhTDCre_minusPrevTDCch0re.push_back(h2);
1561 AddHistoToVector(h2);
1562*/
1563 /* histoName.Form("fhTDC%dre_corrected1", iTDC);
1564 histoTitle.Form("TDC %d re corrected1;channel;ns", iTDC);
1565 TH2D* h3 = new TH2D(histoName, histoTitle, 32, 0., 32., 1200, 0., 600.);
1566 fhTDCre_corrected1.push_back(h3);
1567 AddHistoToVector(h3);
1568
1569 histoName.Form("fhTDC%dre_corrected2", iTDC);
1570 histoTitle.Form("TDC %d re corrected2;channel;ns", iTDC);
1571 TH2D* h4 = new TH2D(histoName, histoTitle, 32, 0., 32., 1200, 0., 600.);
1572 fhTDCre_corrected2.push_back(h4);
1573 AddHistoToVector(h4);
1574*/
1575 // TODO
1576 //workaround we need to init all histograms for ToT here. Otherwise they will not be added to monitoring.
1577 for (Int_t iCh = 0; iCh <= 32; iCh++) {
1578 Int_t tdc = fUnpackPar->GetAddress(iTDC);
1579 GetTotH1(tdc, iCh);
1580 }
1581 {
1582 Int_t tdc = fUnpackPar->GetAddress(iTDC);
1583 GetTotH2(tdc);
1584 }
1585
1586 /*******************************************************************/
1587
1589 { //if (iTDC == 0){
1590 Double_t w = 10;
1591 Double_t h = 10;
1592
1593 TCanvas* c;
1594 TString canvasName;
1595 TString canvasTitle;
1596 Int_t tdc = fUnpackPar->GetAddress(iTDC);
1597 canvasName.Form("cToT2d_TDC_0x%4x", tdc);
1598 canvasTitle.Form("ToTs of TDC 0x%4x", tdc);
1599 c = new TCanvas(canvasName, canvasTitle, w, h);
1600 // fcHitMaps->Divide( 2 );
1601 // fcHitMaps->cd( 1 );
1602 // gPad->SetGridx();
1603 // gPad->SetGridy();
1604 // gPad->SetLogy();
1605 // fhChannelMap->Draw();
1606 // fcHitMaps->cd( 2 );
1607 // gPad->SetGridx();
1608 // gPad->SetGridy();
1609 // gPad->SetLogz();
1610 TH2D* h2 = GetTotH2(tdc);
1611 h2->Draw("colz");
1612 fcTot2d.push_back(c);
1613 AddCanvasToVector(c, "ToT_Canvases");
1614 }
1615 /*******************************************************************/
1616 }
1617
1618
1621
1622 fhVectorSize = new TH1I("fhVectorSize", "Size of the vector VS TS index; TS index; Size [bytes]", 10000, 0., 10000.);
1624 new TH1I("fhVectorCapacity", "Size of the vector VS TS index; TS index; Size [bytes]", 10000, 0., 10000.);
1627
1628 if (fbDebugMonitorMode) {
1629 fhEventSize = new TH1I("fhEventSize", "Size of the Event from TrbNet; Size [bytes]", 350, 0., 70000.);
1631
1633 new TH2I("fhSubEventSize", "fhSubEventSize; HubId ; Size [bytes]; Entries", 6, 0, 6, 10000, 0., 10000.);
1635
1637 new TH2I("fhSubSubEventSize", "fhSubSubEventSize; DiRICH ; Size [words]; Entries", 72, 0, 72, 510, 0., 510.);
1639
1640 fhChnlSize = new TH2I("fhChnlSize", "fhChnlSize; channel; Size [words]; Entries", 33, 0, 33, 25, 0, 25.);
1642 }
1643
1644 return kTRUE;
1645}
1646
1647TH1D* CbmMcbm2018UnpackerAlgoRich2020::GetTotH1(Int_t tdc, Int_t channel)
1648{
1649 TH1D* h = fhTotMap[tdc][channel];
1650 if (h == nullptr) {
1651 TString name, title, subFolder;
1652 name.Form("ToT_tdc0x%x_ch%u", tdc, channel);
1653 title.Form("%s;ToT [ns];Entries", name.Data());
1654 subFolder.Form("ToT/tdc0x%x", tdc);
1655 h = new TH1D(name, title, 100, -1., 49.);
1656 AddHistoToVector(h, std::string(subFolder.Data()));
1657 fhTotMap[tdc][channel] = h;
1658 }
1659 return h;
1660}
1661
1663{
1664 TH2D* h = fhTot2dMap[tdc];
1665 if (h == nullptr) {
1666 TString name, title, subFolder;
1667 name.Form("ToT_2d_tdc0x%x", tdc);
1668 title.Form("%s;channels;ToT [ns]", name.Data());
1669 subFolder.Form("ToT2d");
1670 h = new TH2D(name, title, 33, 0, 32, 200, -1., 49.);
1671 AddHistoToVector(h, std::string(subFolder.Data()));
1672 fhTot2dMap[tdc] = h;
1673 }
1674 return h;
1675}
1676
1677Bool_t CbmMcbm2018UnpackerAlgoRich2020::DebugMs(const fles::Timeslice& ts, size_t uMsCompIdx, size_t uMsIdx)
1678{
1679 const fles::MicrosliceView mv = ts.get_microslice(uMsCompIdx, uMsIdx);
1680 const fles::MicrosliceDescriptor& msDesc = mv.desc();
1681 const uint8_t* ptr = mv.content();
1682 const size_t size = msDesc.size;
1683
1684 if (size == 0) return kTRUE;
1685 Debug(ptr, size);
1686
1687 return kTRUE;
1688}
1689
1690Int_t CbmMcbm2018UnpackerAlgoRich2020::Debug(const uint8_t* ptr, const size_t size)
1691{
1692
1693 if (size == 0) return size;
1694
1695 //LOG(info)<<"DEBUG MODE IS ACTIVE; Printing raw data:";
1696
1697 uint8_t nblCnt = 0;
1698 uint8_t wrdCnt = 0;
1699 std::cout << std::endl << "SIZE: " << std::dec << size << "Byte" << std::endl;
1700 for (size_t i = 0; i < size; ++i) {
1701
1702 //if (wrdCnt == 0) std::cout<<"HEX: ";
1703 uint8_t* tdcDataPtr = (uint8_t*) (ptr + i);
1704
1705 if (wrdCnt == 0 && nblCnt == 0) { printf("%08d : ", static_cast<int>(i)); }
1706
1707 printf("%02x", unsigned(*tdcDataPtr));
1708 nblCnt++;
1709 if (nblCnt % 2 == 0) { printf(" "); }
1710 if (nblCnt % 4 == 0) {
1711 printf(" ");
1712 wrdCnt++;
1713 nblCnt = 0;
1714 }
1715
1716 if (wrdCnt == 10) {
1717 printf("\n");
1718 wrdCnt = 0;
1719 }
1720 }
1721 printf("\n");
1722 return size;
1723}
1724
1725
1726void CbmMcbm2018UnpackerAlgoRich2020::ErrorMsg(uint16_t errbits, RichErrorType type, uint16_t tdcAddr)
1727{
1728 if (fbMonitorMode) {
1729 switch (type) {
1731 //UDP problem
1732 if ((errbits & 0x1) == 1) fhEventErrors->Fill(0.0, 0.0);
1733
1734 break;
1735
1737 // min. 1 rinǵ buffer overwritten
1738 if ((errbits & 0x1) == 1) fhTdcErrors->Fill(fMapFEE[tdcAddr], 0.0);
1739
1740 break;
1741
1743 // no reference time in trigger handler in TDC
1744 if (((errbits >> 0) & 0x1) == 1) fhTdcErrors->Fill(fMapFEE[tdcAddr], 1.0);
1745
1746 // reference time precedes a non-timing trigger
1747 if (((errbits >> 1) & 0x1) == 1) fhTdcErrors->Fill(fMapFEE[tdcAddr], 2.0);
1748
1749 // timing trigger is delivered without a reference time
1750 if (((errbits >> 2) & 0x1) == 1) fhTdcErrors->Fill(fMapFEE[tdcAddr], 3.0);
1751
1752 // Set with the bit 2 to mark the missing reference time
1753 if (((errbits >> 3) & 0x1) == 1) fhTdcErrors->Fill(fMapFEE[tdcAddr], 4.0);
1754
1755 // there are more than one detected reference time
1756 if (((errbits >> 4) & 0x1) == 1) fhTdcErrors->Fill(fMapFEE[tdcAddr], 5.0);
1757
1758 // reference time was too short (<40 ns)
1759 if (((errbits >> 5) & 0x1) == 1) fhTdcErrors->Fill(fMapFEE[tdcAddr], 6.0);
1760
1761 // no trigger validation arrives from the endpoint after a valid reference time
1762 if (((errbits >> 6) & 0x1) == 1) fhTdcErrors->Fill(fMapFEE[tdcAddr], 7.0);
1763
1764 // any timing trigger type except 0x1 is send
1765 if (((errbits >> 7) & 0x1) == 1) fhTdcErrors->Fill(fMapFEE[tdcAddr], 8.0);
1766
1767 break;
1768
1770 // To be implemented
1771 break;
1772
1774 // To be implemented
1775 break;
1776
1778 // event number mismatch
1779 if (((errbits >> 0) & 0x1) == 1) fhEventErrors->Fill(0.0, 1.0);
1780
1781 // trigger code mismatch
1782 if (((errbits >> 1) & 0x1) == 1) fhEventErrors->Fill(0.0, 2.0);
1783
1784 // wrong length
1785 if (((errbits >> 2) & 0x1) == 1) fhEventErrors->Fill(0.0, 3.0);
1786
1787 // answer missing
1788 if (((errbits >> 3) & 0x1) == 1) fhEventErrors->Fill(0.0, 4.0);
1789
1790 // event number request by CTS was not available (Not found)
1791 if (((errbits >> 4) & 0x1) == 1) fhEventErrors->Fill(0.0, 5.0);
1792
1793 // event partially found in data buffer
1794 if (((errbits >> 5) & 0x1) == 1) fhEventErrors->Fill(0.0, 6.0);
1795
1796 // Severe Problem with data buffer and/or read-out
1797 if (((errbits >> 6) & 0x1) == 1) fhEventErrors->Fill(0.0, 7.0);
1798
1799 // Single broken event
1800 if (((errbits >> 7) & 0x1) == 1) fhEventErrors->Fill(0.0, 8.0);
1801
1802 // Ethernet Link down
1803 if (((errbits >> 8) & 0x1) == 1) fhEventErrors->Fill(0.0, 9.0);
1804
1805 // SubEvent buffer almost full
1806 if (((errbits >> 9) & 0x1) == 1) fhEventErrors->Fill(0.0, 10.0);
1807
1808 // Ethernet/SubEventBuilder error
1809 if (((errbits >> 10) & 0x1) == 1) fhEventErrors->Fill(0.0, 11.0);
1810
1811 // Timing trigger error
1812 if (((errbits >> 11) & 0x1) == 1) fhEventErrors->Fill(0.0, 12.0);
1813
1814 break;
1815
1816 default: break;
1817 }
1818 }
1819}
1820
1821/*
1822Bool_t CbmMcbm2018UnpackerAlgoRich2020::FillHistograms()
1823{
1824 return kTRUE;
1825}
1826*/
1828{
1829 //TODO: do something?
1830 return kTRUE;
1831}
1832
1833void CbmMcbm2018UnpackerAlgoRich2020::findTDCAlignmentError(uint8_t const* const ptr, size_t const size)
1834{
1835
1837
1838 // mRichSupport::SwapBytes(4, ptr+size);
1839 // if((((((Int_t*)(ptr+size))[0]) >> 28) & 0xF) != 0x0) {
1840 // LOG(warning) << "CbmMcbm2018UnpackerAlgoRich2020::ProcessTRBsubevent() warning:"
1841 // << "End on Hub is not where expected. Is it a Buffer overflow? LastWord: "<<mRichSupport::GetWordHexRepr(ptr+size);
1842 // }
1843 // mRichSupport::SwapBytes(4, ptr+size);
1844
1845 /***
1846 * Signature of Error:
1847 * 82b7 8ca6
1848 * 8297 *34ad*
1849 * *34ad* 66af // data Ptr
1850 * *cf8b* *cf8b*
1851 * 82c8 cca9
1852 */
1853
1854 //start at 8 to skip header of Hub and first row as this has to be checked
1855 //stop at size -4 to avoid comparing with following hub
1856
1857 for (Int_t i = 8; i < static_cast<Int_t>(size - 4); i += 4) { // i represents bytes (4 per line)
1858 //TODO: Optimize the swaping
1859 mRichSupport::SwapBytes(4, ptr + i - 4);
1860 mRichSupport::SwapBytes(4, ptr + i);
1861 mRichSupport::SwapBytes(4, ptr + i + 4);
1862 bool problem = false;
1863 // clang-format off
1864 if ((((Int_t*) (ptr + i - 4))[0] & 0xFFFF) == ((((Int_t*) (ptr + i))[0] >> 16) & 0xFFFF)) {
1865 if ((((Int_t*) (ptr + i + 4))[0] & 0xFFFF) == ((((Int_t*) (ptr + i + 4))[0] >> 16) & 0xFFFF)) {
1866 //Signature of problem!
1867 problem = true;
1868 fTDCAlignmentErrorPositions.push_back(i);
1869 fTDCAlignmentErrorPositions.push_back(i + 6);
1870 }
1871 }
1872 // clang-format on
1873
1874 mRichSupport::SwapBytes(4, ptr + i - 4);
1875 mRichSupport::SwapBytes(4, ptr + i);
1876 mRichSupport::SwapBytes(4, ptr + i + 4);
1877
1878 if (problem) i += 8; //jump after the problem
1879 }
1880}
1881
ClassImp(CbmConverterManager)
static constexpr size_t size()
Definition KfSimdPseudo.h:2
Int_t GetNaddresses(void) const
Double_t GetToTshift(Int_t tdc, Int_t ch) const
Int_t GetAddress(Int_t ind) const
Int_t GetAddressIdx(Int_t addr, bool bVerbose=true) const
void AddMsComponentToList(size_t component, UShort_t usDetectorId)
TH1D * GetTotH1(Int_t fpgaID, Int_t channel)
Int_t ProcessCTSsubevent(size_t const size, uint8_t const *const ptr)
TrbNetState fTrbState
flag for an error in the datastream
Bool_t fbDoToTCorr
User setting: kTRUE activates ToT correction from Parameterfile.
void ProcessFallingEdge(Int_t subSubEvId, Int_t channel, Double_t time)
std::vector< CbmMcbmRichEdge > fFallingEdgesBuf
Exclude from ROOT dictionnary due to missing empty constructor!!
Int_t ProcessTRBevent(size_t const size, uint8_t const *const ptr)
Int_t ProcessTRBsubsubevent(size_t const size, uint8_t const *const ptr, Int_t const hubOffset, size_t const hubSize)
Bool_t fRawDataMode
Switch ON the filling of a additional set of histograms.
Bool_t DebugMs(const fles::Timeslice &ts, size_t uMsCompIdx, size_t uMsIdx)
Double_t fdTimeOffsetNs
User settings: Data correction parameters.
std::vector< CbmMcbmRichEdge > fRisingEdgesBuf
Int_t ProcessTRBeventHeader(size_t const size, uint8_t const *const ptr)
void ErrorMsg(uint16_t errbits, RichErrorType type, uint16_t tdcAddr=0)
Int_t ProcessTRBsubevent(size_t const size, uint8_t const *const ptr)
void findTDCAlignmentError(uint8_t const *const ptr, size_t const size)
Int_t Debug(const uint8_t *ptr, const size_t size)
void ProcessRisingEdge(Int_t subSubEvId, Int_t channel, Double_t time)
virtual Bool_t ProcessMs(const fles::Timeslice &ts, size_t uMsCompIdx, size_t uMsIdx)
Int_t GetPixelUID(Int_t fpgaID, Int_t ch) const
Int_t ProcessSKIPsubevent(size_t const size, uint8_t const *const ptr)
Int_t ProcessTDCword(uint8_t const *const ptr, Int_t const word, size_t const size)
Bool_t fbDebugMonitorMode
Switch ON the filling of a minimal set of histograms.
std::map< Int_t, std::map< Int_t, TH1D * > > fhTotMap
virtual Bool_t ProcessTs(const fles::Timeslice &ts)
void WriteOutputDigi(Int_t fpgaID, Int_t channel, Double_t time, Double_t tot, uint64_t MSidx)
Bool_t CreateHistograms()
Exclude from ROOT dictionnary due to missing empty constructor!!
void AddHistoToVector(TNamed *pointer, std::string sFolder="")
std::vector< size_t > fvMsComponentsList
void AddCanvasToVector(TCanvas *pointer, std::string sFolder="")
std::vector< CbmRichDigi > fDigiVect
Data class with information on a STS local track.
std::string GetHexRepresentation(size_t const size, uint8_t const *const ptr)
std::string GetWordHexRepr(uint8_t const *const ptr)
void SwapBytes(size_t const size, uint8_t const *ptr)