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, std::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 std::uint32_t frame, std::uint16_t criId,
59 std::uint8_t crobId, std::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 std::uint32_t frame, std::uint16_t criId, std::uint8_t crobId,
77 std::uint16_t elinkId)
78{
80 if (fOptOutBVec) {
81 fOptOutBVec->emplace_back(std::make_pair(fLastFulltime, frame));
82 }
83 fNrCreatedInfoMsgs++;
84 Spadic::MsInfoType infotype = getInfoType(frame, criId, crobId, elinkId);
85 // "Spadic_Info_Types";
86
87 if (fMonitor) {
88 // ModuleId is the asic address after the first 3 digits
89 auto moduleid = getAsicAddress(criId, crobId, elinkId) / 1000;
90 fMonitor->FillHisto(infotype, moduleid);
91 }
92}
93
94// ---- digestInfoMsg ----
95void CbmTrdUnpackAlgoR::digestMsFlags(const std::uint16_t flags, std::uint16_t criId, std::uint8_t crobId)
96{
97 // ModuleId is the asic address after the first 3 digits
98 auto moduleid = getAsicAddress(criId, crobId, 0) / 1000;
99
100 if (flags & static_cast<std::uint16_t>(fles::MicrosliceFlags::CrcValid)) {
101 fNrCrcValidFlags++;
102 if (fMonitor) {
103 fMonitor->FillHisto(fles::MicrosliceFlags::CrcValid, moduleid);
104 }
105 }
106 if (flags & static_cast<std::uint16_t>(fles::MicrosliceFlags::OverflowFlim)) {
107 fNrOverflowFlimFlags++;
108 if (fMonitor) {
109 fMonitor->FillHisto(fles::MicrosliceFlags::OverflowFlim, moduleid);
110 }
111 }
112 if (flags & static_cast<std::uint16_t>(fles::MicrosliceFlags::OverflowUser)) {
113 fNrOverflowUserFlags++;
114 if (fMonitor) {
115 fMonitor->FillHisto(fles::MicrosliceFlags::OverflowUser, moduleid);
116 }
117 }
118 if (flags & static_cast<std::uint16_t>(fles::MicrosliceFlags::DataError)) {
119 fNrDataErrorFlags++;
120 if (fMonitor) {
121 fMonitor->FillHisto(fles::MicrosliceFlags::DataError, moduleid);
122 }
123 }
124}
125
126// ---- extractSample ----
127std::float_t CbmTrdUnpackAlgoR::extractAvgSample(size_t* adcbuffer, size_t* nadcbits)
128{
129 if (*nadcbits < 9)
130 LOG(error) << fName << "::extractAvgSample can not extract samples from a buffer with less than 9 bits";
131
132 *nadcbits -= 9;
133
134 // The decoding of the average sample is kind of interesting:
135 // We get 9 bits in total iiiiiiiff. The 7 "i" bits refer to std integer bits, hence,
136 // covering a range of 0..128.
137 // The 2 "f" bits refer to values after a fix point refering to [0,0.25,0.5,0.75].
138 // The sign we have to assume to be negative (bit-9 = 1) and also bit 8 of our std
139 // interger range we have to assume to be 0, such that the returned number is in
140 // between -256..-128.
141
142 // Activate the 7 "i" bits
143 std::int16_t sample = 0x07f;
144
145 // Write the content of the 7 "i" bits to temp
146 sample &= (*adcbuffer >> (*nadcbits + 2));
147
148 // Switch on the negative sign
149 sample |= 0xff00;
150
151 return sample;
152}
153
154// ---- extractSample ----
155std::int16_t CbmTrdUnpackAlgoR::extractSample(size_t* adcbuffer, size_t* nadcbits)
156{
157 if (*nadcbits < 9)
158 LOG(error) << fName << "::extractSample can not extract samples from a buffer with less than 9 bits";
159
160 // 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
161 *nadcbits -= 9;
162
163 std::int16_t temp = 0x1ff;
164 temp &= (*adcbuffer >> (*nadcbits));
165
166 // Now we have our 9 bits stored in temp, but for a std::int16_t this does not match in terms of the sign handling.
167 // 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
168
169 std::int16_t sample = (temp & 0x0100) ? (temp | 0xff00) : temp;
170
171 return sample;
172}
173
174// ---- finishDerived ----
176{
177 LOG(info) << fName << " \n " << fNrWildRda << " unexpected RDA frames,\n " << fNrWildNul
178 << " unexpected NUL frames, \n " << fNrWildEom << " unexpected EOM frames, \n " << fNrMissingEom
179 << " missing EOM frames, \n " << fNrCorruptEom << " corrupt EOM frames, \n " << fNrElinkMis
180 << " SOM to RDA/EOM eLink mismatches, \n " << fNrNonMajorTsMsb << " non-major ts_msbs and \n "
181 << fNrUnknownWords << " unknown frames." << std::endl;
182}
183
184// ---- getInfoType ----
185Spadic::MsInfoType CbmTrdUnpackAlgoR::getInfoType(const std::uint32_t frame, std::uint16_t criId, std::uint8_t crobId,
186 std::uint16_t elinkId)
187{
188 // Set first 20 bits to 1 for the mask
189 size_t mask = 0x000FFFFF;
190
191 // 000011.................. : BOM word
192 // 0000010................. : MSB word
193 // 0000011................. : BUF word
194 // 0000100................. : UNU word
195 // 0000101................. : MIS word
196
197 if (((frame & mask) >> 18) == 3) // BOM
198 {
200 }
201 if (((frame & mask) >> 17) == 2) // MSB
202 {
204 }
205 if (((frame & mask) >> 17) == 3) // BUF
206 {
207 digestBufInfoFlags(frame, criId, crobId, elinkId);
209 }
210 if (((frame & mask) >> 17) == 4) // UNU
211 {
213 }
214 if (((frame & mask) >> 17) == 5) // MIS
215 {
217 }
218 else {
219 LOG(error) << fName << "::GetInfoType] unknown type!";
221 }
222}
223
224// ---- getMessageType ----
226{
227 std::uint32_t checkframe = frame;
228 checkframe &= 0xffffff;
229 if ((checkframe >> 21) == 1) // SOM 001. ....
230 {
232 }
233 else if ((checkframe >> 22) == 1) // RDA 01.. ....
234 {
236 }
237 else if ((checkframe >> 20) == 1) // EOM 0001 ....
238 {
240 }
241 else if ((checkframe >> 22) == 3) // TS_MSB 11.. ....
242 {
244 }
245 else if (0 < (checkframe >> 18) && (checkframe >> 18) <= 3) {
247 }
248 else if (checkframe == 0) // Last Word in a Microslice is 0
249 {
251 }
252 else // not a spadic message
253 {
255 }
256}
257
258// ---- getTsMsb ----
259std::uint8_t CbmTrdUnpackAlgoR::getTsMsb(const std::uint32_t frame)
260{
261 if ((frame & 0xf) > 0)
262 return -2; // if a 'error' ts_msb is received the tsmsb value is not correct. To not mess up the counting -2 is returned.
263 // 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
264 std::uint8_t tsmsb[3];
265 for (uint iepoch = 0; iepoch < 3; ++iepoch) {
266 tsmsb[iepoch] = static_cast<std::uint8_t>((frame >> (4 + 6 * iepoch) & 0x3f));
267 }
268
269 // 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.
270 if (tsmsb[0] == tsmsb[1] || tsmsb[0] == tsmsb[2]) return tsmsb[0];
271
272 // 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
273 if (tsmsb[1] == tsmsb[2]) return tsmsb[1];
274
275 LOG(debug) << fName
276 << "::checkMajorityTsMsb got a vector without a majority ts_msb, so please check what is going on here!";
278
279 return tsmsb[0];
280}
281
282// ---- makeDigi ----
284{
285
286 // Extract the trigger type and translate it to the digi enum
287 auto rawTriggerType = static_cast<Spadic::eTriggerType>(raw.GetHitType());
288 auto triggerType = CbmTrdRawToDigiBaseR::GetDigiTriggerType(rawTriggerType);
289
290 // Get the digi error class (dummy for the time being)
291 Int_t errClass = 0;
292
293 // Get the address of the originating spadic
294 auto asicAddress = getAsicAddress(raw.GetCriId(), raw.GetCrobId(), raw.GetElinkId());
295
296 // Get the unique module id from the asic address
297 Int_t uniqueModuleId = asicAddress / 1000;
298
299 // Get the channel id on the module
300 auto padChNr = getChannelId(asicAddress, raw.GetElinkId(), raw.GetChannelId());
301
302 // Store the full time information to last full-time member for error message handling
303 fLastFulltime = raw.GetFullTime();
304
305 // Get the time information and apply the necessary correction
306 ULong64_t time = raw.GetTime();
307
308 time -= fSystemTimeOffset;
309 time -= GetElinkTimeOffset(raw.GetCriId(), raw.GetElinkId());
310
311 auto digi = fRTDMethod->MakeDigi(raw.GetSamples(), padChNr, uniqueModuleId, time, triggerType, errClass);
312
313 // If the raw message was flagged as multi hit, forward this info to the digi
314 if (raw.GetMultiHit()) digi->SetTriggerType(CbmTrdDigi::eTriggerType::kMulti);
315
316 // Digest the output, i.e. write to return vector and optional pass to the monitor
317 digestOutput(std::move(digi), raw);
318}
319
320// ---- makeDigi ----
322{
323 auto rawTriggerType = static_cast<Spadic::eTriggerType>(fw.ht);
324 auto triggerType = CbmTrdRawToDigiBaseR::GetDigiTriggerType(rawTriggerType);
325
326 // Get the address of the originating spadic
327 auto asicAddress = getAsicAddress(criid, 0, fw.elink);
328 if (asicAddress) {
329 // Get the unique module id from the asic address
330 Int_t uniqueModuleId = asicAddress / 1000;
331
332 // Get the channel id on the module
333 auto padChNr = getChannelId(asicAddress, fw.elink, fw.channel);
334
335 // Store the full time information to last full-time member for error message handling
336 // Get the time information and apply the necessary correction
337 ULong64_t time = (fw.timestamp - fw.prec_time) * fSpadic->GetClockCycle() + fMsStartTimeRel;
338
339 auto energy = fSpadic->MaxAdcToEnergyCal(fw.maxAdc);
340
341 time -= fSystemTimeOffset;
342 time -= GetElinkTimeOffset(criid, fw.elink);
343
344 auto digi = std::unique_ptr<CbmTrdDigi>(new CbmTrdDigi(padChNr, uniqueModuleId, energy, time, triggerType, 0));
345
346 // If the message was flagged as multi hit, forward this info to the digi
347 if (fw.mh != 0) digi->SetTriggerType(CbmTrdDigi::eTriggerType::kMulti);
348
349 //pass digi to monitor
350 if (fMonitor) {
351 fMonitor->FillHistos(digi.get(), nullptr);
352 }
353
354 fOutputVec.emplace_back(*std::move(digi));
355 }
356}
357
358// ---- makeRaw ----
359CbmTrdRawMessageSpadic CbmTrdUnpackAlgoR::makeRaw(const std::uint32_t frame, std::uint16_t criId, std::uint8_t crobId,
360 std::uint16_t elinkId, std::uint8_t istream)
361{
362
363 auto chId = static_cast<std::uint8_t>(((frame >> 17) & 0xf));
364 auto timestamp = static_cast<std::uint8_t>((frame >> 9) & 0xff);
365 bool multihit = ((frame >> 8) & 0x1);
366 auto hitType = static_cast<std::uint8_t>((frame >> 6) & 0x3);
367 std::uint8_t nsamples = 0;
368 // We directly start with the largest possible samples vector to only init it once
369 std::vector<std::int16_t> samples = std::vector<std::int16_t>(0);
370
371 uint64_t fulltime = fMsStartTimeRelCC + (fNrTsMsbVec.at(istream) * fTsMsbLengthCC) + timestamp;
372
373
374 // Create message
375 CbmTrdRawMessageSpadic retval(chId, elinkId, crobId, criId, hitType, nsamples, multihit, fulltime, samples);
376 return retval;
377}
378
379
380// ---- unpack ----
381bool CbmTrdUnpackAlgoR::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice)
382{
383 bool unpackOk = true;
384
385 if (fMonitor) fMonitor->SetCurrentTimesliceStartTime(fTsStartTime);
386
387 auto msdesc = ts->descriptor(icomp, imslice);
388
389 // Get the µSlice starttime relative to the timeslice starttime.
390 // 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
391 fMsStartTimeRel = msdesc.idx - fTsStartTime;
392 fMsStartTimeRelCC = fMsStartTimeRel / fSpadic->GetClockCycle();
393
394 // Get the hardware ids from which the current µSlice is coming
395 std::uint8_t crobId = 0;
396 auto criId = msdesc.eq_id;
397
398 // Digest the flags from the µSlice
399 digestMsFlags(msdesc.flags, criId, crobId);
400
401 const auto mspointer = ts->content(icomp, imslice);
402
403 const auto mscontent = reinterpret_cast<const size_t*>(mspointer);
404
405 if (msdesc.sys_ver == 0x10) {
406 return unpackFex<0x10>(msdesc, mscontent);
407 }
408 else {
409 return unpackRaw(msdesc, mscontent);
410 }
411 return unpackOk;
412}
413
414bool CbmTrdUnpackAlgoR::unpackRaw(const fles::MicrosliceDescriptor msdesc, const size_t* mscontent)
415{
416
417 // Get the µslice size in bytes to calculate the number of completed words
418 auto mssize = msdesc.size;
419
420 // We have 32 bit spadic frames in this readout version
421 std::uint32_t nwords = mssize / fBytesPerWord;
422
423 // Get the hardware ids from which the current µSlice is coming
424 std::uint8_t crobId = 0;
425 auto criId = msdesc.eq_id;
426
427 bool unpackOk = true;
428 // 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.
429 std::int8_t currTsMsb = 0;
430
431 // Reset the TS_MSB counter for the new µSlice we unpack
432 fNrTsMsbVec.clear();
434
435 // Loop over all 64bit-Spadic-Words in the current µslice
436 for (std::uint32_t istream = 0; istream < fStreamsPerWord; istream++) {
437 currTsMsb = -1;
438 for (std::uint32_t iword = 0; iword < nwords; ++iword) {
439 // Access the actual word from the pointer
440 size_t word = static_cast<size_t>(mscontent[iword]);
441
442 // Access the actual frame[iframe] from the word. (see fStreamsPerWord)
443 std::uint32_t frame = (word >> (32 * istream)) & 0xffffffff;
444
445 // Get the type of the frame
446 auto kWordtype = getMessageType(frame);
447
448 // 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
449 auto elinkId = (frame >> 24) & 0x3f;
450
451 switch (kWordtype) {
453 auto tsmsb = getTsMsb(frame);
454 if (((tsmsb - currTsMsb) & 0x3f) == 1 || currTsMsb == -1) fNrTsMsbVec.at(istream)++;
455 currTsMsb = tsmsb;
456 fNrEpochMsgs++;
457 break;
458 // FIXME in the kEPO msg we also have further flags that should be extracted
459 }
461 // Create the raw message and fill it with all information we can get from the SOM msg
462 CbmTrdRawMessageSpadic raw = makeRaw(frame, criId, crobId, elinkId, istream);
463
464 // 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
465 // 6 adc bits are stored in the som message
466 size_t nadcbits = 6;
467 size_t nadcbitstotal = 6;
468 // Get the first bits from the adc signal
469 size_t adcbuffer = frame & 0x3f;
470 size_t isample = 0;
471 size_t irda = 0;
472
473 // Now lets check if we have rda words following our som
474 iword++;
475 word = static_cast<size_t>(mscontent[iword]);
476 frame = (word >> (32 * istream)) & 0xffffffff;
477
478 // The maximum amount of samples (32) equals to 12 RDA messages
479 while (getMessageType(frame) == Spadic::MsMessageType::kRDA && irda < 12) {
480 // We have to count the number of rda frames for sample reconstruction in eom
481 irda++;
482
483 // Ensure that we are on the correct eLink
484 elinkId = (frame >> 24) & 0x3f;
485 if (elinkId != raw.GetElinkId()) {
486 fNrElinkMis++;
487 LOG(debug) << fName << "::unpack() SOM eLinkId(" << static_cast<std::uint16_t>(raw.GetElinkId())
488 << ") does not match the RDA eLinkId(" << elinkId << ")";
489 }
490
491 // We have 22 adc bits per RDA word lets add them to the buffer...
492 adcbuffer <<= 22;
493 adcbuffer |= static_cast<size_t>((frame & 0x3fffff));
494 // and increase the adcbit counter by 22 bits
495 nadcbits += 22;
496 nadcbitstotal += 22;
497 // If we have 9 or more samples stored we can extract n samples
498 while (nadcbits >= 9) {
499 raw.IncNrSamples();
500 // In case the avg baseline feature was used we need to take special care of sample 0
501 if (isample == 0 && fSpadic->GetUseBaselineAvg())
502 raw.SetSample(extractAvgSample(&adcbuffer, &nadcbits), isample);
503 else
504 raw.SetSample(extractSample(&adcbuffer, &nadcbits), isample);
505 isample++;
506 }
507 iword++;
508 word = static_cast<size_t>(mscontent[iword]);
509 frame = (word >> (32 * istream)) & 0xffffffff;
510 }
511
513 // Ensure that we are on the correct eLink
514 elinkId = (frame >> 24) & 0x3f;
515 if (elinkId != raw.GetElinkId()) {
516 fNrElinkMis++;
517 LOG(debug) << fName << "::unpack() SOM eLinkId(" << static_cast<std::uint16_t>(raw.GetElinkId())
518 << ") does not match the RDA eLinkId(" << elinkId << ")";
519 }
520
521 // Number of samples indicator = nsamples % 4
522 std::uint8_t nsamplesindicator = (frame >> 18) & 0x3;
523 // Number of required samples as indicated
524 std::uint64_t nreqsamples = (nadcbitstotal + 18) / 9;
525 std::uint8_t nn = nreqsamples % 4;
526 for (std::uint8_t itest = 0; itest < 3; itest++) {
527 if (nn == nsamplesindicator || nreqsamples == 0) break;
528 nreqsamples--;
529 nn = nreqsamples % 4;
530 }
531
532 // 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
533 if (nreqsamples >= isample) {
534 // Now extract from the above values the number of required adc bits from the eom
535 std::int8_t nrequiredbits = (nreqsamples - isample) * 9 - nadcbits;
536 adcbuffer <<= nrequiredbits;
537
538 // The eom carries at maximum 18 adcbits
539 adcbuffer |= static_cast<size_t>((frame & 0x3ffff) >> (18 - nrequiredbits));
540 nadcbits += nrequiredbits;
541
542 while (nadcbits >= 9) {
543 raw.IncNrSamples();
544 raw.SetSample(extractSample(&adcbuffer, &nadcbits), isample);
545 isample++;
546 }
547 }
548 else {
550 }
551 ++fNrCreatedRawMsgs;
552
553 // 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.
554 if (isample > 0) makeDigi(raw);
555 }
556 else {
557 // We move the word counter backwards by one, such that the unexpected message can correctly be digested
558 iword--;
560 LOG(debug)
561 << fName
562 << "::unpack() We had a SOM message and hence, desparately need an EOM message but none came. This "
563 "is quite mysterious and a problem!";
564 }
565 break;
566 }
568 LOG(debug) << fName << "::unpack() Unexpected wild RDA word";
569 fNrWildRda++;
570 break;
571 }
573 LOG(debug) << fName << "::unpack() Unexpected wild EOM word";
574 fNrWildEom++;
575 break;
576 }
578 digestInfoMsg(frame, criId, crobId, elinkId);
579 break;
580 }
582 if (iword != (nwords - 1) || (istream != (fStreamsPerWord - 1)))
583 // last word in Microslice is 0.
584 {
585 LOG(debug) << fName
586 << "::unpack() Null Word but "
587 "not at end of Microslice.";
588 fNrWildNul++;
589 }
590 break;
591 }
593 LOG(debug) << fName
594 << "::unpack() Unknown Word. "
595 "Microslice corrupted.";
597 return false;
598 break;
599 }
600 default:
601 // We have varying msg types for different versions of the message format. Hence, to not produce compiler warnings we have a "default break;" here.
602 break;
603 }
604 }
605 }
606 return unpackOk;
607}
608
609template<std::uint8_t sys_ver>
610bool CbmTrdUnpackAlgoR::unpackFex(const fles::MicrosliceDescriptor msdesc, const size_t* mscontent)
611{
612 constexpr std::uint8_t bytes = Spadic::BytesPerWord<sys_ver>();
613 if constexpr (bytes == 0) {
614 // TODO log something
615 return false;
616 }
617 bool unpackOk = true;
618
619 // Get the µslice size in bytes to calculate the number of completed words
620 auto mssize = msdesc.size;
621 std::uint32_t nwords = mssize / bytes;
622 // Get the hardware ids from which the current µSlice is coming
623 std::uint8_t crobId = 0;
624 auto criId = msdesc.eq_id;
625
626 const Spadic::NByteContainer<bytes>* bp = reinterpret_cast<const Spadic::NByteContainer<bytes>*>(mscontent);
627
628 for (std::uint32_t iword = 0; iword < nwords; ++iword) {
629 Spadic::NByteContainer<bytes> bCont = bp[iword];
630 Spadic::FexWord<sys_ver> fw(bCont);
631 if (fw.ht != 0) {
632 makeDigi(fw, criId);
633 }
634 }
635 return unpackOk;
636}
637
638template bool CbmTrdUnpackAlgoR::unpackFex<0x10>(const fles::MicrosliceDescriptor msdesc, const size_t* mscontent);
639
ClassImp(CbmConverterManager)
Assign pad layout to TRD Modules.
Software representation of the SPADIC v2.2+.
Unpacker algorithm for the TrdR 2021 data.
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
const std::vector< std::int16_t > * GetSamples() const
void IncNrSamples()
increase the number of samples stored in this raw message by one
std::uint8_t GetChannelId() const
void SetSample(std::int16_t value, std::uint8_t pos)
std::uint8_t GetCrobId() const
std::uint8_t GetHitType() const
std::uint8_t GetElinkId() const
std::uint16_t GetCriId() 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.
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.
size_t fNrUnknownWords
Number of unknown words.
std::int32_t GetElinkTimeOffset(std::uint32_t criid, std::uint8_t elinkid)
Get the time offeset to be substracted from the digis which come from a specific CRI.
virtual std::uint32_t getAsicAddress(std::uint32_t criid, std::uint32_t crobid, std::uint32_t elinkid)
Get the Asic Address (CbmAddress scheme) for the given hardware Ids.
std::uint32_t getChannelId(std::uint32_t asicaddress, std::uint32_t elinkid, std::uint32_t elinkchannelid)
Get the Channel Id (CbmAddress scheme) for the given hardware Ids.
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 µSlice.
size_t fNrCorruptEom
Number of corrupted EOM frames.
static const std::uint8_t fStreamsPerWord
Number of streams per word For the msg format used from 2021 ongoing we have 2 parallel streams per w...
virtual CbmTrdRawMessageSpadic makeRaw(const std::uint32_t frame, std::uint16_t criId, std::uint8_t crobId, std::uint16_t elinkId, std::uint8_t istream)
Create a CbmTrdRawMessageSpadic from the hit message input.
void makeDigi(CbmTrdRawMessageSpadic raw)
Create an actual digi from the raw message.
CbmTrdUnpackAlgoR()
Create the Cbm Trd Unpack AlgoBase object.
Spadic::MsMessageType getMessageType(const std::uint32_t frame)
Identify the message type of a given 32bit frame inside a Microslice.
std::int16_t extractSample(size_t *adcbuffer, size_t *nadcbits)
Extract all adc samples from a given adcbuffer container.
std::uint8_t getTsMsb(const std::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...
void finishDerived()
Additional explicit finish function of this algo implementation.
bool unpackRaw(const fles::MicrosliceDescriptor msdesc, const size_t *mscontent)
Spadic::MsInfoType digestBufInfoFlags(const std::uint32_t frame, std::uint16_t criId, std::uint8_t crobId, std::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...
virtual std::vector< std::pair< std::string, std::shared_ptr< FairParGenericSet > > > * GetParContainerRequest(std::string geoTag, std::uint32_t runId)
Get the requested parameter containers. Return the required parameter containers together with the pa...
bool unpackFex(const fles::MicrosliceDescriptor msdesc, const size_t *mscontent)
std::vector< std::uint8_t > fNrTsMsbVec
Counter for the ts_msb used to reconstruct the time.
size_t fNrNonMajorTsMsb
Counter for the ts_msb used to reconstruct the time.
void digestInfoMsg(const std::uint32_t frame, std::uint16_t criId, std::uint8_t crobId, std::uint16_t elinkId)
Digest a info message run all default information forwarding from the msg.
void digestMsFlags(const std::uint16_t flags, std::uint16_t criId, std::uint8_t crobId)
Digest the flags of the currently unpacked µSlice.
virtual ~CbmTrdUnpackAlgoR()
Destroy the Cbm Trd Unpack Task object.
static const std::uint8_t fBytesPerWord
Bytes per spadic frame stored in the microslices.
Spadic::MsInfoType getInfoType(const std::uint32_t frame, std::uint16_t criId, std::uint8_t crobId, std::uint16_t elinkId)
Identify the InfoType of a 64bit InfoMessage word inside a Microslice.
size_t fMsStartTimeRelCC
Start time of the current µSlice relative to the Timeslice start time in Spadic CC.
bool unpack(const fles::Timeslice *ts, std::uint16_t icomp, UInt_t imslice)
Unpack a given microslice.
size_t fNrElinkMis
Number of SOM to RDA/EOM mismatches.
size_t fMsStartTimeRel
Start time of the current µ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.
@ kNUL
Microslice End.
@ kSOM
Start of Message.
@ kEPO
Epoch Marker or TS_MSB depending on the hitmessage version.
@ kEOM
End of Message.
@ kUNK
Unkown Word.
@ kINF
Info Message.
constexpr std::uint8_t BytesPerWord()