CbmRoot
Loading...
Searching...
No Matches
CbmTrdUnpackAlgoR.cxx
Go to the documentation of this file.
1/* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Pascal Raisig [committer] */
4
5#include "CbmTrdUnpackAlgoR.h"
6
7#include "CbmTrdParManager.h"
8#include "CbmTrdParSetAsic.h"
10#include "CbmTrdSpadic.h"
11
12#include <FairTask.h>
13#include <Logger.h>
14
15#include <RtypesCore.h>
16
17#include <algorithm>
18#include <bitset>
19#include <cstdint>
20#include <memory>
21#include <typeinfo>
22
24
26
27
28// ---- GetParContainerRequest ----
29std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>*
30CbmTrdUnpackAlgoR::GetParContainerRequest(std::string geoTag, uint32_t runId)
31{
32 // Basepath for default Trd parameter sets (those connected to a geoTag)
33 std::string basepath = Form("%s/trd_%s", fParFilesBasePath.data(), geoTag.data());
34 std::string temppath = "";
35
36 // Digest the runId information in case of runId = 0 we use the default fall back
37 std::string runpath = "";
38 if (runId != 0) {
39 runpath = ".run" + std::to_string(runId);
40 }
41
42 // Get .asic parameter container
43 temppath = basepath + runpath + ".asic" + ".par";
44 fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmTrdParSetAsic>()));
45
46 // Currently we need the ParSetDigi only for the monitor
47 if (fMonitor) {
48 temppath = basepath + runpath + ".digi" + ".par";
49 auto pair = std::make_pair(temppath, std::make_shared<CbmTrdParSetDigi>());
50 fParContVec.emplace_back(pair);
51 }
52
53
54 return &fParContVec;
55}
56
57// ---- digestBufInfoFlags ----
58Spadic::MsInfoType CbmTrdUnpackAlgoR::digestBufInfoFlags(const uint32_t frame, uint16_t criId, uint8_t crobId,
59 uint16_t elinkId)
60{
61 auto flag = (frame >> 15) & 0x3;
62 Spadic::MsInfoType infotype;
63 if (flag == 1) infotype = Spadic::MsInfoType::kChannelBuf;
64 if (flag == 2) infotype = Spadic::MsInfoType::kOrdFifoBuf;
65 if (flag == 3) infotype = Spadic::MsInfoType::kChannelBufM;
66
67 if (fMonitor) {
68 // ModuleId is the asic address after the first 3 digits
69 auto moduleid = getAsicAddress(criId, crobId, elinkId) / 1000;
70 fMonitor->FillHisto(infotype, moduleid);
71 }
72 return infotype;
73}
74
75// ---- digestInfoMsg ----
76void CbmTrdUnpackAlgoR::digestInfoMsg(const uint32_t frame, uint16_t criId, uint8_t crobId, uint16_t elinkId)
77{
79 if (fOptOutBVec) {
80 fOptOutBVec->emplace_back(std::make_pair(fLastFulltime, frame));
81 }
82 fNrCreatedInfoMsgs++;
83 Spadic::MsInfoType infotype = getInfoType(frame, criId, crobId, elinkId);
84 // "Spadic_Info_Types";
85
86 if (fMonitor) {
87 // ModuleId is the asic address after the first 3 digits
88 auto moduleid = getAsicAddress(criId, crobId, elinkId) / 1000;
89 fMonitor->FillHisto(infotype, moduleid);
90 }
91}
92
93// ---- digestInfoMsg ----
94void CbmTrdUnpackAlgoR::digestMsFlags(const uint16_t flags, uint16_t criId, uint8_t crobId)
95{
96 // ModuleId is the asic address after the first 3 digits
97 auto moduleid = getAsicAddress(criId, crobId, 0) / 1000;
98
99 if (flags & static_cast<uint16_t>(fles::MicrosliceFlags::CrcValid)) {
100 fNrCrcValidFlags++;
101 if (fMonitor) {
102 fMonitor->FillHisto(fles::MicrosliceFlags::CrcValid, moduleid);
103 }
104 }
105 if (flags & static_cast<uint16_t>(fles::MicrosliceFlags::OverflowFlim)) {
106 fNrOverflowFlimFlags++;
107 if (fMonitor) {
108 fMonitor->FillHisto(fles::MicrosliceFlags::OverflowFlim, moduleid);
109 }
110 }
111 if (flags & static_cast<uint16_t>(fles::MicrosliceFlags::OverflowUser)) {
112 fNrOverflowUserFlags++;
113 if (fMonitor) {
114 fMonitor->FillHisto(fles::MicrosliceFlags::OverflowUser, moduleid);
115 }
116 }
117 if (flags & static_cast<uint16_t>(fles::MicrosliceFlags::DataError)) {
118 fNrDataErrorFlags++;
119 if (fMonitor) {
120 fMonitor->FillHisto(fles::MicrosliceFlags::DataError, moduleid);
121 }
122 }
123}
124
125// ---- extractSample ----
126std::float_t CbmTrdUnpackAlgoR::extractAvgSample(size_t* adcbuffer, size_t* nadcbits)
127{
128 if (*nadcbits < 9)
129 LOG(error) << fName << "::extractAvgSample can not extract samples from a buffer with less than 9 bits";
130
131 *nadcbits -= 9;
132
133 // The decoding of the average sample is kind of interesting:
134 // We get 9 bits in total iiiiiiiff. The 7 "i" bits refer to std integer bits, hence,
135 // covering a range of 0..128.
136 // The 2 "f" bits refer to values after a fix point refering to [0,0.25,0.5,0.75].
137 // The sign we have to assume to be negative (bit-9 = 1) and also bit 8 of our std
138 // interger range we have to assume to be 0, such that the returned number is in
139 // between -256..-128.
140
141 // Activate the 7 "i" bits
142 int16_t sample = 0x07f;
143
144 // Write the content of the 7 "i" bits to temp
145 sample &= (*adcbuffer >> (*nadcbits + 2));
146
147 // Switch on the negative sign
148 sample |= 0xff00;
149
150 return sample;
151}
152
153// ---- extractSample ----
154int16_t CbmTrdUnpackAlgoR::extractSample(size_t* adcbuffer, size_t* nadcbits)
155{
156 if (*nadcbits < 9)
157 LOG(error) << fName << "::extractSample can not extract samples from a buffer with less than 9 bits";
158
159 // We want to access the bits stored at the positions between nadcbits and nadcbits - 9, so we can already here reduce nadcbits by 9 and than shift the adcbuffer by this value to the right and compare it with temp which has the 9 lsbs set to 1
160 *nadcbits -= 9;
161
162 int16_t temp = 0x1ff;
163 temp &= (*adcbuffer >> (*nadcbits));
164
165 // Now we have our 9 bits stored in temp, but for a int16_t this does not match in terms of the sign handling.
166 // So we check on bit 9 for the sign (temp & 0x0100) and if we have a negative value we manipulate bit 16-10 to 1 to get the correct negative number
167
168 int16_t sample = (temp & 0x0100) ? (temp | 0xff00) : temp;
169
170 return sample;
171}
172
173// ---- finishDerived ----
175{
176 LOG(info) << fName << " \n " << fNrWildRda << " unexpected RDA frames,\n " << fNrWildNul
177 << " unexpected NUL frames, \n " << fNrWildEom << " unexpected EOM frames, \n " << fNrMissingEom
178 << " missing EOM frames, \n " << fNrCorruptEom << " corrupt EOM frames, \n " << fNrElinkMis
179 << " SOM to RDA/EOM eLink mismatches, \n " << fNrNonMajorTsMsb << " non-major ts_msbs and \n "
180 << fNrUnknownWords << " unknown frames." << std::endl;
181}
182
183// ---- getInfoType ----
184Spadic::MsInfoType CbmTrdUnpackAlgoR::getInfoType(const uint32_t frame, uint16_t criId, uint8_t crobId,
185 uint16_t elinkId)
186{
187 // Set first 20 bits to 1 for the mask
188 size_t mask = 0x000FFFFF;
189
190 // 000011.................. : BOM word
191 // 0000010................. : MSB word
192 // 0000011................. : BUF word
193 // 0000100................. : UNU word
194 // 0000101................. : MIS word
195
196 if (((frame & mask) >> 18) == 3) // BOM
197 {
199 }
200 if (((frame & mask) >> 17) == 2) // MSB
201 {
203 }
204 if (((frame & mask) >> 17) == 3) // BUF
205 {
206 digestBufInfoFlags(frame, criId, crobId, elinkId);
208 }
209 if (((frame & mask) >> 17) == 4) // UNU
210 {
212 }
213 if (((frame & mask) >> 17) == 5) // MIS
214 {
216 }
217 else {
218 LOG(error) << fName << "::GetInfoType] unknown type!";
220 }
221}
222
223// ---- getMessageType ----
225{
226 uint32_t checkframe = frame;
227 checkframe &= 0xffffff;
228 if ((checkframe >> 21) == 1) // SOM 001. ....
229 {
231 }
232 else if ((checkframe >> 22) == 1) // RDA 01.. ....
233 {
235 }
236 else if ((checkframe >> 20) == 1) // EOM 0001 ....
237 {
239 }
240 else if ((checkframe >> 22) == 3) // TS_MSB 11.. ....
241 {
243 }
244 else if (0 < (checkframe >> 18) && (checkframe >> 18) <= 3) {
246 }
247 else if (checkframe == 0) // Last Word in a Microslice is 0
248 {
250 }
251 else // not a spadic message
252 {
254 }
255}
256
257// ---- getTsMsb ----
258uint8_t CbmTrdUnpackAlgoR::getTsMsb(const uint32_t frame)
259{
260 if ((frame & 0xf) > 0)
261 return -2; // if a 'error' ts_msb is received the tsmsb value is not correct. To not mess up the counting -2 is returned.
262 // The epoch in form of the TS_MSBs is written 3 times into the frame to allow to check for bit flips and catch errors. It has the length of 6 bits and an offset of 4
263 uint8_t tsmsb[3];
264 for (uint iepoch = 0; iepoch < 3; ++iepoch) {
265 tsmsb[iepoch] = static_cast<uint8_t>((frame >> (4 + 6 * iepoch) & 0x3f));
266 }
267
268 // Check if the epoch at position 0 is at least compatible with one of the others. Since, we only have 3 that value is automatically the majority value.
269 if (tsmsb[0] == tsmsb[1] || tsmsb[0] == tsmsb[2]) return tsmsb[0];
270
271 // If we arrive here the epoch at position 0 is not compatible with the other two. So let's check if they are compatible with each other. If so we have again a majority epoch
272 if (tsmsb[1] == tsmsb[2]) return tsmsb[1];
273
274 LOG(debug) << fName
275 << "::checkMajorityTsMsb got a vector without a majority ts_msb, so please check what is going on here!";
277
278 return tsmsb[0];
279}
280
281// ---- makeDigi ----
283{
284
285 // Extract the trigger type and translate it to the digi enum
286 auto rawTriggerType = static_cast<Spadic::eTriggerType>(raw.GetHitType());
287 auto triggerType = CbmTrdRawToDigiBaseR::GetDigiTriggerType(rawTriggerType);
288
289 // Get the digi error class (dummy for the time being)
290 Int_t errClass = 0;
291
292 // Get the address of the originating spadic
293 auto asicAddress = getAsicAddress(raw.GetCriId(), raw.GetCrobId(), raw.GetElinkId());
294
295 // Get the unique module id from the asic address
296 Int_t uniqueModuleId = asicAddress / 1000;
297
298 // Get the channel id on the module
299 auto padChNr = getChannelId(asicAddress, raw.GetElinkId(), raw.GetChannelId());
300
301 // Store the full time information to last full-time member for error message handling
302 fLastFulltime = raw.GetFullTime();
303
304 // Get the time information and apply the necessary correction
305 ULong64_t time = raw.GetTime();
306
307 time -= fSystemTimeOffset;
308 time -= GetElinkTimeOffset(raw.GetCriId(), raw.GetElinkId());
309
310 auto digi = fRTDMethod->MakeDigi(raw.GetSamples(), padChNr, uniqueModuleId, time, triggerType, errClass);
311
312 // If the raw message was flagged as multi hit, forward this info to the digi
313 if (raw.GetMultiHit()) digi->SetTriggerType(CbmTrdDigi::eTriggerType::kMulti);
314
315 // Digest the output, i.e. write to return vector and optional pass to the monitor
316 digestOutput(std::move(digi), raw);
317}
318
319// ---- makeDigi ----
321{
322 auto rawTriggerType = static_cast<Spadic::eTriggerType>(fw.ht);
323 auto triggerType = CbmTrdRawToDigiBaseR::GetDigiTriggerType(rawTriggerType);
324
325 // Get the address of the originating spadic
326 auto asicAddress = getAsicAddress(criid, 0, fw.elink);
327 if (asicAddress) {
328 // Get the unique module id from the asic address
329 Int_t uniqueModuleId = asicAddress / 1000;
330
331 // Get the channel id on the module
332 auto padChNr = getChannelId(asicAddress, fw.elink, fw.channel);
333
334 // Store the full time information to last full-time member for error message handling
335 // Get the time information and apply the necessary correction
336 ULong64_t time = (fw.timestamp - fw.prec_time) * fSpadic->GetClockCycle() + fMsStartTimeRel;
337
338 auto energy = fSpadic->MaxAdcToEnergyCal(fw.maxAdc);
339
340 time -= fSystemTimeOffset;
341 time -= GetElinkTimeOffset(criid, fw.elink);
342
343 auto digi = std::unique_ptr<CbmTrdDigi>(new CbmTrdDigi(padChNr, uniqueModuleId, energy, time, triggerType, 0));
344
345 // If the message was flagged as multi hit, forward this info to the digi
346 if (fw.mh != 0) digi->SetTriggerType(CbmTrdDigi::eTriggerType::kMulti);
347
348 //pass digi to monitor
349 if (fMonitor) {
350 fMonitor->FillHistos(digi.get(), nullptr);
351 }
352
353 fOutputVec.emplace_back(*std::move(digi));
354 }
355}
356
357// ---- makeRaw ----
358CbmTrdRawMessageSpadic CbmTrdUnpackAlgoR::makeRaw(const uint32_t frame, uint16_t criId, uint8_t crobId,
359 uint16_t elinkId, uint8_t istream)
360{
361
362 auto chId = static_cast<uint8_t>(((frame >> 17) & 0xf));
363 auto timestamp = static_cast<uint8_t>((frame >> 9) & 0xff);
364 bool multihit = ((frame >> 8) & 0x1);
365 auto hitType = static_cast<uint8_t>((frame >> 6) & 0x3);
366 uint8_t nsamples = 0;
367 // We directly start with the largest possible samples vector to only init it once
368 std::vector<int16_t> samples = std::vector<int16_t>(0);
369
370 uint64_t fulltime = fMsStartTimeRelCC + (fNrTsMsbVec.at(istream) * fTsMsbLengthCC) + timestamp;
371
372
373 // Create message
374 CbmTrdRawMessageSpadic retval(chId, elinkId, crobId, criId, hitType, nsamples, multihit, fulltime, samples);
375 return retval;
376}
377
378
379// ---- unpack ----
380bool CbmTrdUnpackAlgoR::unpack(const fles::Timeslice* ts, uint16_t icomp, UInt_t imslice)
381{
382 bool unpackOk = true;
383
384 if (fMonitor) fMonitor->SetCurrentTimesliceStartTime(fTsStartTime);
385
386 auto msdesc = ts->descriptor(icomp, imslice);
387
388 // Get the micro-Slice starttime relative to the timeslice starttime.
389 // The UTC is already to large for storing it CbmTrdRawMessageSpadic due to a cast, caused by the multiplication with a double used in the raw message
390 fMsStartTimeRel = msdesc.idx - fTsStartTime;
391 fMsStartTimeRelCC = fMsStartTimeRel / fSpadic->GetClockCycle();
392
393 // Get the hardware ids from which the current micro-Slice is coming
394 uint8_t crobId = 0;
395 auto criId = msdesc.eq_id;
396
397 // Digest the flags from the micro-Slice
398 digestMsFlags(msdesc.flags, criId, crobId);
399
400 const auto mspointer = ts->content(icomp, imslice);
401
402 const auto mscontent = reinterpret_cast<const size_t*>(mspointer);
403
404 if (msdesc.sys_ver == 0x10) {
405 return unpackFex<0x10>(msdesc, mscontent);
406 }
407 else {
408 return unpackRaw(msdesc, mscontent);
409 }
410 return unpackOk;
411}
412
413bool CbmTrdUnpackAlgoR::unpackRaw(const fles::MicrosliceDescriptor msdesc, const size_t* mscontent)
414{
415
416 // Get the micro-slice size in bytes to calculate the number of completed words
417 auto mssize = msdesc.size;
418
419 // We have 32 bit spadic frames in this readout version
420 uint32_t nwords = mssize / fBytesPerWord;
421
422 // Get the hardware ids from which the current micro-Slice is coming
423 uint8_t crobId = 0;
424 auto criId = msdesc.eq_id;
425
426 bool unpackOk = true;
427 // We only want to count on TS_MSB per Stream per TS_MSB package (each eLink sends its own TS_MSB frame) so we store the current TS_MSB and compare it to the incoming.
428 int8_t currTsMsb = 0;
429
430 // Reset the TS_MSB counter for the new micro-Slice we unpack
431 fNrTsMsbVec.clear();
433
434 // Loop over all 64bit-Spadic-Words in the current micro-slice
435 for (uint32_t istream = 0; istream < fStreamsPerWord; istream++) {
436 currTsMsb = -1;
437 for (uint32_t iword = 0; iword < nwords; ++iword) {
438 // Access the actual word from the pointer
439 size_t word = static_cast<size_t>(mscontent[iword]);
440
441 // Access the actual frame[iframe] from the word. (see fStreamsPerWord)
442 uint32_t frame = (word >> (32 * istream)) & 0xffffffff;
443
444 // Get the type of the frame
445 auto kWordtype = getMessageType(frame);
446
447 // In case we saw any other word than an EPO(TS_MSB) reset the flag, such that we again increase by one if an EPO frame arrives
448 auto elinkId = (frame >> 24) & 0x3f;
449
450 switch (kWordtype) {
452 auto tsmsb = getTsMsb(frame);
453 if (((tsmsb - currTsMsb) & 0x3f) == 1 || currTsMsb == -1) fNrTsMsbVec.at(istream)++;
454 currTsMsb = tsmsb;
455 fNrEpochMsgs++;
456 break;
457 // FIXME in the kEPO msg we also have further flags that should be extracted
458 }
460 // Create the raw message and fill it with all information we can get from the SOM msg
461 CbmTrdRawMessageSpadic raw = makeRaw(frame, criId, crobId, elinkId, istream);
462
463 // FIXME since we can not deduce the sample position from the messages we need in future some parameter handling here to place the samples at the correct position
464 // 6 adc bits are stored in the som message
465 size_t nadcbits = 6;
466 size_t nadcbitstotal = 6;
467 // Get the first bits from the adc signal
468 size_t adcbuffer = frame & 0x3f;
469 size_t isample = 0;
470 size_t irda = 0;
471
472 // Now lets check if we have rda words following our som
473 iword++;
474 word = static_cast<size_t>(mscontent[iword]);
475 frame = (word >> (32 * istream)) & 0xffffffff;
476
477 // The maximum amount of samples (32) equals to 12 RDA messages
478 while (getMessageType(frame) == Spadic::MsMessageType::kRDA && irda < 12) {
479 // We have to count the number of rda frames for sample reconstruction in eom
480 irda++;
481
482 // Ensure that we are on the correct eLink
483 elinkId = (frame >> 24) & 0x3f;
484 if (elinkId != raw.GetElinkId()) {
485 fNrElinkMis++;
486 LOG(debug) << fName << "::unpack() SOM eLinkId(" << static_cast<uint16_t>(raw.GetElinkId())
487 << ") does not match the RDA eLinkId(" << elinkId << ")";
488 }
489
490 // We have 22 adc bits per RDA word lets add them to the buffer...
491 adcbuffer <<= 22;
492 adcbuffer |= static_cast<size_t>((frame & 0x3fffff));
493 // and increase the adcbit counter by 22 bits
494 nadcbits += 22;
495 nadcbitstotal += 22;
496 // If we have 9 or more samples stored we can extract n samples
497 while (nadcbits >= 9) {
498 raw.IncNrSamples();
499 // In case the avg baseline feature was used we need to take special care of sample 0
500 if (isample == 0 && fSpadic->GetUseBaselineAvg())
501 raw.SetSample(extractAvgSample(&adcbuffer, &nadcbits), isample);
502 else
503 raw.SetSample(extractSample(&adcbuffer, &nadcbits), isample);
504 isample++;
505 }
506 iword++;
507 word = static_cast<size_t>(mscontent[iword]);
508 frame = (word >> (32 * istream)) & 0xffffffff;
509 }
510
512 // Ensure that we are on the correct eLink
513 elinkId = (frame >> 24) & 0x3f;
514 if (elinkId != raw.GetElinkId()) {
515 fNrElinkMis++;
516 LOG(debug) << fName << "::unpack() SOM eLinkId(" << static_cast<uint16_t>(raw.GetElinkId())
517 << ") does not match the RDA eLinkId(" << elinkId << ")";
518 }
519
520 // Number of samples indicator = nsamples % 4
521 uint8_t nsamplesindicator = (frame >> 18) & 0x3;
522 // Number of required samples as indicated
523 uint64_t nreqsamples = (nadcbitstotal + 18) / 9;
524 uint8_t nn = nreqsamples % 4;
525 for (uint8_t itest = 0; itest < 3; itest++) {
526 if (nn == nsamplesindicator || nreqsamples == 0) break;
527 nreqsamples--;
528 nn = nreqsamples % 4;
529 }
530
531 // There is a chance that the nsamplesindicator bits are corrupted, here we check that we do not try to extract more adcbits than actually are streamed
532 if (nreqsamples >= isample) {
533 // Now extract from the above values the number of required adc bits from the eom
534 int8_t nrequiredbits = (nreqsamples - isample) * 9 - nadcbits;
535 adcbuffer <<= nrequiredbits;
536
537 // The eom carries at maximum 18 adcbits
538 adcbuffer |= static_cast<size_t>((frame & 0x3ffff) >> (18 - nrequiredbits));
539 nadcbits += nrequiredbits;
540
541 while (nadcbits >= 9) {
542 raw.IncNrSamples();
543 raw.SetSample(extractSample(&adcbuffer, &nadcbits), isample);
544 isample++;
545 }
546 }
547 else {
549 }
550 ++fNrCreatedRawMsgs;
551
552 // the message is done and the raw message container should contain everything we need. So now we can call makeDigi(). Nevertheless there is a chance for a corrupted message, which ends up with 0 samples so we have to check for it.
553 if (isample > 0) makeDigi(raw);
554 }
555 else {
556 // We move the word counter backwards by one, such that the unexpected message can correctly be digested
557 iword--;
559 LOG(debug)
560 << fName
561 << "::unpack() We had a SOM message and hence, desparately need an EOM message but none came. This "
562 "is quite mysterious and a problem!";
563 }
564 break;
565 }
567 LOG(debug) << fName << "::unpack() Unexpected wild RDA word";
568 fNrWildRda++;
569 break;
570 }
572 LOG(debug) << fName << "::unpack() Unexpected wild EOM word";
573 fNrWildEom++;
574 break;
575 }
577 digestInfoMsg(frame, criId, crobId, elinkId);
578 break;
579 }
581 if (iword != (nwords - 1) || (istream != (fStreamsPerWord - 1)))
582 // last word in Microslice is 0.
583 {
584 LOG(debug) << fName
585 << "::unpack() Null Word but "
586 "not at end of Microslice.";
587 fNrWildNul++;
588 }
589 break;
590 }
592 LOG(debug) << fName
593 << "::unpack() Unknown Word. "
594 "Microslice corrupted.";
596 return false;
597 break;
598 }
599 default:
600 // We have varying msg types for different versions of the message format. Hence, to not produce compiler warnings we have a "default break;" here.
601 break;
602 }
603 }
604 }
605 return unpackOk;
606}
607
608template<uint8_t sys_ver>
609bool CbmTrdUnpackAlgoR::unpackFex(const fles::MicrosliceDescriptor msdesc, const size_t* mscontent)
610{
611 constexpr uint8_t bytes = Spadic::BytesPerWord<sys_ver>();
612 if constexpr (bytes == 0) {
613 // TODO log something
614 return false;
615 }
616 bool unpackOk = true;
617
618 // Get the micro-slice size in bytes to calculate the number of completed words
619 auto mssize = msdesc.size;
620 uint32_t nwords = mssize / bytes;
621 // Get the hardware ids from which the current micro-Slice is coming
622 uint8_t crobId = 0;
623 auto criId = msdesc.eq_id;
624
625 const Spadic::NByteContainer<bytes>* bp = reinterpret_cast<const Spadic::NByteContainer<bytes>*>(mscontent);
626
627 for (uint32_t iword = 0; iword < nwords; ++iword) {
628 Spadic::NByteContainer<bytes> bCont = bp[iword];
629 Spadic::FexWord<sys_ver> fw(bCont);
630 if (fw.ht != 0) {
631 makeDigi(fw, criId);
632 }
633 }
634 return unpackOk;
635}
636
637template bool CbmTrdUnpackAlgoR::unpackFex<0x10>(const fles::MicrosliceDescriptor msdesc, const size_t* mscontent);
638
ClassImp(CbmConverterManager)
Assign pad layout to TRD Modules.
Software representation of the SPADIC v2.2+.
Unpacker algorithm for the TrdR 2021 data.
int Int_t
Base class for storing raw information which comes from the Spadic v2.2 trough flib or from a tsa fil...
void SetSample(int16_t value, uint8_t pos)
void IncNrSamples()
increase the number of samples stored in this raw message by one
const std::vector< int16_t > * GetSamples() const
static CbmTrdDigi::eTriggerType GetDigiTriggerType(Spadic::eTriggerType tt)
Get the Digi Trigger Type from the raw message triggertype.
std::shared_ptr< CbmTrdRawToDigiBaseR > fRTDMethod
raw to digi extraction method, set in the task
void digestOutput(std::unique_ptr< CbmTrdDigi > digi, CbmTrdRawMessageSpadic raw)
Handle the output created by the explicit algorithms. E.g. write to output vectors.
virtual uint32_t getAsicAddress(uint32_t criid, uint32_t crobid, uint32_t elinkid)
Get the Asic Address (CbmAddress scheme) for the given hardware Ids.
size_t fNrMissingEom
Number of missing EOM frames to finish a SOM frame.
size_t fTsMsbLengthCC
length of one ts_msb in [cc]
std::shared_ptr< CbmTrdUnpackMonitor > fMonitor
Potential (online) monitor for the unpacking process.
std::shared_ptr< CbmTrdSpadic > fSpadic
Spadic software reprensentation object.
size_t fNrWildRda
Number of rda frames outside of a SOM frame range.
uint32_t getChannelId(uint32_t asicaddress, uint32_t elinkid, uint32_t elinkchannelid)
Get the Channel Id (CbmAddress scheme) for the given hardware Ids.
int32_t GetElinkTimeOffset(uint32_t criid, uint8_t elinkid)
Get the time offeset to be substracted from the digis which come from a specific CRI.
size_t fNrUnknownWords
Number of unknown words.
CbmTrdUnpackAlgoBaseR(std::string name)
Create the Cbm Trd Unpack AlgoBase object.
size_t fNrWildEom
Number of eom frames outside of a SOM frame range.
size_t fNrWildNul
Number of wild null words, should only appear at the end of a micro-Slice.
std::vector< uint8_t > fNrTsMsbVec
Counter for the ts_msb used to reconstruct the time.
static const uint8_t fBytesPerWord
Bytes per spadic frame stored in the microslices.
size_t fNrCorruptEom
Number of corrupted EOM frames.
static const uint8_t fStreamsPerWord
Number of streams per word For the msg format used from 2021 ongoing we have 2 parallel streams per w...
void makeDigi(CbmTrdRawMessageSpadic raw)
Create an actual digi from the raw message.
virtual std::vector< std::pair< std::string, std::shared_ptr< FairParGenericSet > > > * GetParContainerRequest(std::string geoTag, uint32_t runId)
Get the requested parameter containers. Return the required parameter containers together with the pa...
CbmTrdUnpackAlgoR()
Create the Cbm Trd Unpack AlgoBase object.
int16_t extractSample(size_t *adcbuffer, size_t *nadcbits)
Extract all adc samples from a given adcbuffer container.
Spadic::MsMessageType getMessageType(const uint32_t frame)
Identify the message type of a given 32bit frame inside a Microslice.
void finishDerived()
Additional explicit finish function of this algo implementation.
bool unpackRaw(const fles::MicrosliceDescriptor msdesc, const size_t *mscontent)
Spadic::MsInfoType digestBufInfoFlags(const uint32_t frame, uint16_t criId, uint8_t crobId, uint16_t elinkId)
Digest the aditional flags stored in the 4 "cccc" bits of the EPO messages.
std::float_t extractAvgSample(size_t *adcbuffer, size_t *nadcbits)
Extract the baseline average sample from a given adcbuffer. Depending on the Spadic settings sample-0...
bool unpackFex(const fles::MicrosliceDescriptor msdesc, const size_t *mscontent)
size_t fNrNonMajorTsMsb
Counter for the ts_msb used to reconstruct the time.
uint8_t getTsMsb(const uint32_t frame)
Get the ts_msb information from the TS_MSB(kEPO) frame. We take the first of the 3 The 3 redundant TS...
virtual ~CbmTrdUnpackAlgoR()
Destroy the Cbm Trd Unpack Task object.
bool unpack(const fles::Timeslice *ts, uint16_t icomp, UInt_t imslice)
Unpack a given microslice.
Spadic::MsInfoType getInfoType(const uint32_t frame, uint16_t criId, uint8_t crobId, uint16_t elinkId)
Identify the InfoType of a 64bit InfoMessage word inside a Microslice.
virtual CbmTrdRawMessageSpadic makeRaw(const uint32_t frame, uint16_t criId, uint8_t crobId, uint16_t elinkId, uint8_t istream)
Create a CbmTrdRawMessageSpadic from the hit message input.
size_t fMsStartTimeRelCC
Start time of the current micro-Slice relative to the Timeslice start time in Spadic CC.
void digestMsFlags(const uint16_t flags, uint16_t criId, uint8_t crobId)
Digest the flags of the currently unpacked micro-Slice.
size_t fNrElinkMis
Number of SOM to RDA/EOM mismatches.
void digestInfoMsg(const uint32_t frame, uint16_t criId, uint8_t crobId, uint16_t elinkId)
Digest a info message run all default information forwarding from the msg.
size_t fMsStartTimeRel
Start time of the current micro-Slice relative to the Timeslice start time in ns.
@ kUNU
Unused request. 100. .... .... .... cccc.
@ kChannelBufM
Channel buffer full and multihit from kEPO msg.
@ kChannelBuf
Channel buffer full from kEPO msg.
@ kBOM
Buffer overflow count. 11nn nnnn nnnn nnnn cccc.
@ kMIS
Missing request. 101. .... .... .... ....
@ kOrdFifoBuf
Multi-hit but ordering buffer full from kEPO msg.
@ kBUF
Buffer full. 011b b... .... .... cccc.
@ kMSB
Message build error. 010. .... .... .... cccc.
@ kEPO
Epoch Marker or TS_MSB depending on the hitmessage version.
constexpr uint8_t BytesPerWord()