CbmRoot
Loading...
Searching...
No Matches
trd/UnpackMS.cxx
Go to the documentation of this file.
1/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Pascal Raisig, Dominik Smith [committer], David Schledt */
4
5#include "UnpackMS.h"
6
8
9#include <algorithm>
10#include <cassert>
11#include <vector>
12
13using std::unique_ptr;
14
15namespace cbm::algo::trd
16{
17
18 // ---- digestBufInfoFlags ----
19 template<uint8_t sys_ver>
21 {
22 auto flag = (frame >> 15) & 0x3;
23 Spadic::MsInfoType infotype;
24 if (flag == 1) infotype = Spadic::MsInfoType::kChannelBuf;
25 if (flag == 2) infotype = Spadic::MsInfoType::kOrdFifoBuf;
26 if (flag == 3) infotype = Spadic::MsInfoType::kChannelBufM;
27 return infotype;
28 }
29
30 template Spadic::MsInfoType UnpackMS<0x01>::digestBufInfoFlags(const std::uint32_t frame) const;
31
32 // ---- digestInfoMsg ----
33 template<uint8_t sys_ver>
34 void UnpackMS<sys_ver>::digestInfoMsg(const std::uint32_t frame) const
35 {
37 //if (fOptOutBVec) { fOptOutBVec->emplace_back(std::make_pair(ctx.fLastFulltime, frame)); }
38 [[maybe_unused]] Spadic::MsInfoType infotype = getInfoType(frame);
39 // "Spadic_Info_Types";
40 }
41
42 template void UnpackMS<0x01>::digestInfoMsg(const std::uint32_t frame) const;
43
44 // ---- digestInfoMsg ----
45 template<uint8_t sys_ver>
46 void UnpackMS<sys_ver>::digestMsFlags(const std::uint16_t flags, UnpackMonitorData& monitor) const
47 {
48 if (flags & static_cast<std::uint16_t>(fles::MicrosliceFlags::CrcValid)) {
49 monitor.fNumCrcValidFlags++;
50 }
51 if (flags & static_cast<std::uint16_t>(fles::MicrosliceFlags::OverflowFlim)) {
52 monitor.fNumOverflowFlimFlags++;
53 }
54 if (flags & static_cast<std::uint16_t>(fles::MicrosliceFlags::OverflowUser)) {
55 monitor.fNumOverflowUserFlags++;
56 }
57 if (flags & static_cast<std::uint16_t>(fles::MicrosliceFlags::DataError)) {
58 monitor.fNumDataErrorFlags++;
59 }
60 }
61
62 template void UnpackMS<0x01>::digestMsFlags(const std::uint16_t flags, UnpackMonitorData& monitor) const;
63 template void UnpackMS<0x10>::digestMsFlags(const std::uint16_t flags, UnpackMonitorData& monitor) const;
64
65 // ---- extractSample ----
66 template<uint8_t sys_ver>
67 std::float_t UnpackMS<sys_ver>::extractAvgSample(size_t* adcbuffer, size_t* nadcbits) const
68 {
69 // can not extract samples from a buffer with less than 9 bits
70 assert(*nadcbits >= 9);
71 *nadcbits -= 9;
72
73 // The decoding of the average sample is kind of interesting:
74 // We get 9 bits in total iiiiiiiff. The 7 "i" bits refer to std integer bits, hence,
75 // covering a range of 0..128.
76 // The 2 "f" bits refer to values after a fix point refering to [0,0.25,0.5,0.75].
77 // The sign we have to assume to be negative (bit-9 = 1) and also bit 8 of our std
78 // interger range we have to assume to be 0, such that the returned number is in
79 // between -256..-128.
80
81 // Activate the 7 "i" bits
82 std::int16_t sample = 0x07f;
83
84 // Write the content of the 7 "i" bits to temp
85 sample &= (*adcbuffer >> (*nadcbits + 2));
86
87 // Switch on the negative sign
88 sample |= 0xff00;
89
90 return sample;
91 }
92
93 template std::float_t UnpackMS<0x01>::extractAvgSample(size_t* adcbuffer, size_t* nadcbits) const;
94
95 // ---- extractSample ----
96 template<uint8_t sys_ver>
97 std::int16_t UnpackMS<sys_ver>::extractSample(size_t* adcbuffer, size_t* nadcbits) const
98 {
99 // can not extract samples from a buffer with less than 9 bits
100 assert(*nadcbits >= 9);
101
102 // We want to access the bits stored at the positions between nadcbits and nadcbits - 9, so we can already here
103 // 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
104 *nadcbits -= 9;
105
106 std::int16_t temp = 0x1ff;
107 temp &= (*adcbuffer >> (*nadcbits));
108
109 // 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.
110 // 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
111 // to get the correct negative number
112 std::int16_t sample = (temp & 0x0100) ? (temp | 0xff00) : temp;
113
114 return sample;
115 }
116
117 template std::int16_t UnpackMS<0x01>::extractSample(size_t* adcbuffer, size_t* nadcbits) const;
118
119 // ---- getInfoType ----
120 template<uint8_t sys_ver>
121 Spadic::MsInfoType UnpackMS<sys_ver>::getInfoType(const std::uint32_t frame) const
122 {
123 // Set first 20 bits to 1 for the mask
124 size_t mask = 0x000FFFFF;
125
126 // 000011.................. : BOM word
127 // 0000010................. : MSB word
128 // 0000011................. : BUF word
129 // 0000100................. : UNU word
130 // 0000101................. : MIS word
131
132 if (((frame & mask) >> 18) == 3) // BOM
133 {
135 }
136 if (((frame & mask) >> 17) == 2) // MSB
137 {
139 }
140 if (((frame & mask) >> 17) == 3) // BUF
141 {
142 digestBufInfoFlags(frame);
144 }
145 if (((frame & mask) >> 17) == 4) // UNU
146 {
148 }
149 if (((frame & mask) >> 17) == 5) // MIS
150 {
152 }
153 else {
154 // TODO: Track this error!
155 L_(error) << "UnpackMS::GetInfoType] unknown type!";
157 }
158 }
159
160 template Spadic::MsInfoType UnpackMS<0x01>::getInfoType(const std::uint32_t frame) const;
161
162 // ---- getMessageType ----
163 template<uint8_t sys_ver>
165 {
166 std::uint32_t checkframe = frame;
167 checkframe &= 0xffffff;
168 if ((checkframe >> 21) == 1) // SOM 001. ....
169 {
171 }
172 else if ((checkframe >> 22) == 1) // RDA 01.. ....
173 {
175 }
176 else if ((checkframe >> 20) == 1) // EOM 0001 ....
177 {
179 }
180 else if ((checkframe >> 22) == 3) // TS_MSB 11.. ....
181 {
183 }
184 else if (0 < (checkframe >> 18) && (checkframe >> 18) <= 3) {
186 }
187 else if (checkframe == 0) // Last Word in a Microslice is 0
188 {
190 }
191 else // not a spadic message
192 {
194 }
195 }
196
197 template Spadic::MsMessageType UnpackMS<0x01>::getMessageType(const std::uint32_t frame) const;
198
199 // ---- getTsMsb ----
200 template<uint8_t sys_ver>
201 std::uint8_t UnpackMS<sys_ver>::getTsMsb(const std::uint32_t frame, UnpackMonitorData& monitor) const
202 {
203 if ((frame & 0xf) > 0)
204 return -2; // if a 'error' ts_msb is received the tsmsb value is not correct. To not mess up the counting -2 is returned.
205 // 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.
206 // It has the length of 6 bits and an offset of 4
207 std::uint8_t tsmsb[3];
208 for (uint iepoch = 0; iepoch < 3; ++iepoch) {
209 tsmsb[iepoch] = static_cast<std::uint8_t>((frame >> (4 + 6 * iepoch) & 0x3f));
210 }
211
212 // Check if the epoch at position 0 is at least compatible with one of the others.
213 // Since, we only have 3 that value is automatically the majority value.
214 if (tsmsb[0] == tsmsb[1] || tsmsb[0] == tsmsb[2]) return tsmsb[0];
215
216 // If we arrive here the epoch at position 0 is not compatible with the other two.
217 // So let's check if they are compatible with each other. If so we have again a majority epoch
218 if (tsmsb[1] == tsmsb[2]) return tsmsb[1];
219
220 monitor.fNumNonMajorTsMsb++;
221
222 return tsmsb[0];
223 }
224
225 template std::uint8_t UnpackMS<0x01>::getTsMsb(const std::uint32_t frame, UnpackMonitorData& monitor) const;
226
227
228 // method definition for specialization
229 template<uint8_t sys_ver>
231 {
232 return CbmTrdDigi();
233 }
234
235 // ---- makeDigi sys_ver <0x10> ----
236 template<>
238 {
239 auto rawTriggerType = static_cast<Spadic::eTriggerType>(fw.ht);
240 auto triggerType = GetDigiTriggerType(rawTriggerType);
241
242 int32_t errClass = 0;
243
244 // Get the address of the originating spadic
245 const UnpackCrobPar& crobPar = fParams.fCrobParams.at(0);
246 const UnpackElinkPar& elinkPar = crobPar.fElinkParams.at(fw.elink);
247 const uint32_t asicAddress = elinkPar.fAddress;
248
249 // Get the channel id on the module
250 int32_t padChNr = elinkPar.fChanAddress.at(fw.channel);
251
252 // Get the time information and apply the necessary correction
253 uint64_t time = (fw.timestamp - fw.prec_time) * fAsicClockCycle + fMsStartTimeRel;
254 time -= elinkPar.fTimeOffset;
255
256 auto energy = fw.maxAdc * fParams.fMaxAdcToEnergyCal;
257
258 // Get the unique module id from the asic address
259 int32_t uniqueModuleId = asicAddress / 1000;
260
261 CbmTrdDigi digi = CbmTrdDigi(padChNr, uniqueModuleId, energy, time, triggerType, errClass);
262
263 // If the message was flagged as multi hit, forward this info to the digi
265
266 return digi;
267 }
268
269 // ---- makeDigi from raw ----
270 template<uint8_t sys_ver>
272 {
273 // Extract the trigger type and translate it to the digi enum
274 auto rawTriggerType = static_cast<Spadic::eTriggerType>(raw.GetHitType());
275 auto triggerType = GetDigiTriggerType(rawTriggerType);
276
277 // Get the digi error class (dummy for the time being)
278 int32_t errClass = 0;
279
280 // Get the address of the originating spadic
281 const UnpackCrobPar& crobPar = fParams.fCrobParams.at(raw.GetCrobId());
282 const UnpackElinkPar& elinkPar = crobPar.fElinkParams.at(raw.GetElinkId());
283 const uint32_t asicAddress = elinkPar.fAddress;
284
285 // Get the channel id on the module
286 int32_t padChNr = elinkPar.fChanAddress.at(raw.GetChannelId());
287
288 // Store the full time information to last full-time member for error message handling
289 ctx.fLastFulltime = raw.GetFullTime();
290
291 // Get the time information and apply the necessary correction
292 uint64_t time = raw.GetTime() - elinkPar.fTimeOffset;
293
294 // Get the timeshift and set the member, which is required for some of the rtd methods
295 uint64_t currentTimeshift = GetBinTimeShift(raw.GetSamples());
296
297 // In simulation since we often start at time = 0 there is a non negligible chance that a time < 0 is extracted.
298 //Since, this is not allowed in the code we set it to 0 for these cases
299 time = time > currentTimeshift ? time - currentTimeshift : 0;
300
301 // In this case of CbmTrdRawToDigi GetCharge calls GetBinTimeshift, since the information is needed.
302 // The shift is stored in fCurrentTimeshift
303 // Hence, the order of charge and time assignement here makes a difference!
304 auto maxadc = GetMaxAdcValue(raw.GetSamples());
305
306 // Get energy from maxadc value
307 auto energy = maxadc * fParams.fMaxAdcToEnergyCal;
308
309 // Get the unique module id from the asic address
310 int32_t uniqueModuleId = asicAddress / 1000;
311
312 CbmTrdDigi digi = CbmTrdDigi(padChNr, uniqueModuleId, energy, time, triggerType, errClass);
313
314 // If the raw message was flagged as multi hit, forward this info to the digi
316
317 return digi;
318 }
319
320 template CbmTrdDigi UnpackMS<0x01>::makeDigi(CbmTrdRawMessageSpadic raw, MsContext& ctx) const;
321
322 // ---- makeRaw ----
323 template<uint8_t sys_ver>
324 CbmTrdRawMessageSpadic UnpackMS<sys_ver>::makeRaw(const std::uint32_t frame, std::uint16_t criId, std::uint8_t crobId,
325 std::uint16_t elinkId, std::uint8_t istream, MsContext& ctx) const
326 {
327 auto chId = static_cast<std::uint8_t>(((frame >> 17) & 0xf));
328 auto timestamp = static_cast<std::uint8_t>((frame >> 9) & 0xff);
329 bool multihit = ((frame >> 8) & 0x1);
330 auto hitType = static_cast<std::uint8_t>((frame >> 6) & 0x3);
331 std::uint8_t nsamples = 0;
332 // We directly start with the largest possible samples vector to only init it once
333 std::vector<std::int16_t> samples = std::vector<std::int16_t>(0);
334
335 uint64_t fulltime = ctx.fMsStartTimeRelCC + (ctx.fNrTsMsbVec.at(istream) * fTsMsbLengthCC) + timestamp;
336
337 // Create message
338 return CbmTrdRawMessageSpadic(chId, elinkId, crobId, criId, hitType, nsamples, multihit, fulltime, samples);
339 }
340
341 template CbmTrdRawMessageSpadic UnpackMS<0x01>::makeRaw(const std::uint32_t frame, std::uint16_t criId,
342 std::uint8_t crobId, std::uint16_t elinkId,
343 std::uint8_t istream, MsContext& ctx) const;
344
345
346 // ---- GetDigiTriggerType ----
347 template<uint8_t sys_ver>
349 {
350 // Shift self trigger to digi selftrigger
351 // Shift neighbour trigger to digi neighbour
352 // Hide spadic kSandN in Self
353 switch (tt) {
358 default: return CbmTrdDigi::eTriggerType::kNTrg;
359 }
360 }
361
364
365 // --- GetCharge ----
366 template<uint8_t sys_ver>
367 float_t UnpackMS<sys_ver>::GetMaxAdcValue(const std::vector<std::int16_t>* samples) const
368 {
369 // Safety for corrupted input samples
370 assert(samples->size() >= fPeakingBinMin);
371
372 // The signal should peak at the shaping time.
373 // The corresponding sample is the peaking time divided by the sample length.
374 auto itbegin = std::next(samples->begin(), fPeakingBinMin);
375
376 // Check if the expected maximum position of the peaking bin exceeds the size of the vector
377 auto nsamples = samples->size();
378 auto peakingBinMax = (nsamples - 1) > fPeakingBinMax ? fPeakingBinMax : nsamples;
379 auto itend = std::next(samples->begin(), peakingBinMax);
380
381 // Get the maximum element
382 auto itmax = std::max_element(itbegin, itend);
383
384 // Get charge and correct for the baseline
385 float_t charge = static_cast<float_t>(*itmax) - GetBaseline(samples);
386
387 // Remark: Due to the fact, that we store the charge UInt_t in the Digi values below 0 are not allowed.
388 // In this case the above only appears if the baseline fluctuated above all values in the applied peaking range.
389 // This can only happen for forced neighbor triggers with a deposited charged that can not be separated from the baseline.
390 return charge > 0 ? charge : 0;
391 }
392
393 template float_t UnpackMS<0x01>::GetMaxAdcValue(const std::vector<std::int16_t>* samples) const;
394
395 // ---- GetBaseline ----
396 template<uint8_t sys_ver>
397 float_t UnpackMS<sys_ver>::GetBaseline(const std::vector<std::int16_t>* samples) const
398 {
399 // The spadic 2.2 has a functionality that an average baseline can be written to the first sample.
400 // So first we have to check if this is active.
401 if (fParams.fUseBaselineAvg)
402 return samples->at(0);
403 else {
404 float_t baseline = 0.0;
405 auto itend = samples->begin() + fNrOfPresamples;
406 if (itend > samples->end()) itend = samples->end();
407 for (auto isample = samples->begin(); isample < itend; isample++) {
408 baseline += *isample;
409 }
410 baseline /= fNrOfPresamples;
411
412 return baseline;
413 }
414 }
415 template float_t UnpackMS<0x01>::GetBaseline(const std::vector<std::int16_t>* samples) const;
416
417 // ---- Algorithm execution sys_ver >= 0x10 ---------------------------------------------
418 template<std::uint8_t sys_ver>
420 const fles::MicrosliceDescriptor& msDescr,
421 const uint64_t tTimeslice) const
422 {
423 Result_t result = {};
424
425
426 // Digest the flags from the µSlice
427 digestMsFlags(msDescr.flags, std::get<1>(result));
428
429 size_t fMsStartTimeRel = (msDescr.idx - tTimeslice);
430
431 // Get bytes per word used for the given system version
432 constexpr std::uint8_t bytes = Spadic::BytesPerWord<sys_ver>();
433
434 auto mssize = msDescr.size;
435 std::uint32_t nwords = mssize / bytes;
436
437 const Spadic::NByteContainer<bytes>* bp = reinterpret_cast<const Spadic::NByteContainer<bytes>*>(msContent);
438
439 for (std::uint32_t iword = 0; iword < nwords; ++iword) {
440 Spadic::NByteContainer<bytes> bCont = bp[iword];
441 Spadic::FexWord<sys_ver> fw(bCont);
442 if (fw.ht != 0) {
443 std::get<0>(result).push_back(makeDigi(fw, fMsStartTimeRel));
444 }
445 }
446 return result;
447 }
448
449 template typename UnpackMS<0x10>::Result_t UnpackMS<0x10>::operator()(const uint8_t* msContent,
450 const fles::MicrosliceDescriptor& msDescr,
451 const uint64_t tTimeslice) const;
452 // --------------------------------------------------------------------------
453
454 // ---- Algorithm execution sys_ver - 0x01 ---------------------------------------------
455 template<>
456 typename UnpackMS<0x01>::Result_t UnpackMS<0x01>::operator()(const uint8_t* msContent,
457 const fles::MicrosliceDescriptor& msDescr,
458 const uint64_t tTimeslice) const
459 {
460 // --- Output data
461 Result_t result = {};
462
463 MsContext ctx = {};
464
465 // Get the µSlice starttime relative to the timeslice starttime (constant is clock length of Spadic in ns)
466 ctx.fMsStartTimeRelCC = (msDescr.idx - tTimeslice) / fAsicClockCycle;
467
468 // We only want to count on TS_MSB per Stream per TS_MSB package (each eLink sends its own TS_MSB frame)
469 // so we store the current TS_MSB and compare it to the incoming.
470 std::int8_t currTsMsb = 0;
471
472 // Reset the TS_MSB counter for the new µSlice we unpack
473 ctx.fNrTsMsbVec.resize(fStreamsPerWord);
474
475
476 // Get the µslice size in bytes to calculate the number of completed words
477 auto mssize = msDescr.size;
478
479 // Get the hardware ids from which the current µSlice is coming
480 std::uint8_t crobId = 0;
481 auto criId = msDescr.eq_id;
482
483 // Digest the flags from the µSlice
484 digestMsFlags(msDescr.flags, std::get<1>(result));
485
486 // Get the number of complete words in the input MS buffer.
487 std::uint32_t nwords = mssize / fBytesPerWord;
488
489 // We have 32 bit spadic frames in this readout version
490 const auto mscontent = reinterpret_cast<const size_t*>(msContent);
491
492 std::get<0>(result).reserve(nwords);
493
494 // Loop over all 64bit-Spadic-Words in the current µslice
495 for (std::uint32_t istream = 0; istream < fStreamsPerWord; istream++) {
496 currTsMsb = -1;
497 for (std::uint32_t iword = 0; iword < nwords; ++iword) {
498 // Access the actual word from the pointer
499 size_t word = static_cast<size_t>(mscontent[iword]);
500
501 // Access the actual frame[iframe] from the word. (see fStreamsPerWord)
502 std::uint32_t frame = (word >> (32 * istream)) & 0xffffffff;
503
504 // Get the type of the frame
505 auto kWordtype = getMessageType(frame);
506
507 // In case we saw any other word than an EPO(TS_MSB) reset the flag,
508 // such that we again increase by one if an EPO frame arrives
509 auto elinkId = (frame >> 24) & 0x3f;
510
511 switch (kWordtype) {
513 auto tsmsb = getTsMsb(frame, std::get<1>(result));
514 if (((tsmsb - currTsMsb) & 0x3f) == 1 || currTsMsb == -1) ctx.fNrTsMsbVec.at(istream)++;
515 currTsMsb = tsmsb;
516 std::get<1>(result).fNumEpochMsgs++;
517 break;
518 // FIXME in the kEPO msg we also have further flags that should be extracted
519 }
521 // Create the raw message and fill it with all information we can get from the SOM msg
522 CbmTrdRawMessageSpadic raw = makeRaw(frame, criId, crobId, elinkId, istream, ctx);
523
524 // FIXME since we can not deduce the sample position from the messages we need in
525 // future some parameter handling here to place the samples at the correct position
526 // 6 adc bits are stored in the som message
527 size_t nadcbits = 6;
528 size_t nadcbitstotal = 6;
529 // Get the first bits from the adc signal
530 size_t adcbuffer = frame & 0x3f;
531 size_t isample = 0;
532 size_t irda = 0;
533
534 // Now lets check if we have rda words following our som
535 iword++;
536 word = static_cast<size_t>(mscontent[iword]);
537 frame = (word >> (32 * istream)) & 0xffffffff;
538
539 // The maximum amount of samples (32) equals to 12 RDA messages
540 while (getMessageType(frame) == Spadic::MsMessageType::kRDA && irda < 12) {
541 // We have to count the number of rda frames for sample reconstruction in eom
542 irda++;
543
544 // Ensure that we are on the correct eLink
545 elinkId = (frame >> 24) & 0x3f;
546 if (elinkId != raw.GetElinkId()) {
547 std::get<1>(result).fNumElinkMis++;
548 }
549
550 // We have 22 adc bits per RDA word lets add them to the buffer...
551 adcbuffer <<= 22;
552 adcbuffer |= static_cast<size_t>((frame & 0x3fffff));
553 // and increase the adcbit counter by 22 bits
554 nadcbits += 22;
555 nadcbitstotal += 22;
556 // If we have 9 or more samples stored we can extract n samples
557 while (nadcbits >= 9) {
558 raw.IncNrSamples();
559 // In case the avg baseline feature was used we need to take special care of sample 0
560 if (isample == 0 && fParams.fUseBaselineAvg)
561 raw.SetSample(extractAvgSample(&adcbuffer, &nadcbits), isample);
562 else
563 raw.SetSample(extractSample(&adcbuffer, &nadcbits), isample);
564 isample++;
565 }
566 iword++;
567 word = static_cast<size_t>(mscontent[iword]);
568 frame = (word >> (32 * istream)) & 0xffffffff;
569 }
570
571 if (getMessageType(frame) == Spadic::MsMessageType::kEOM) {
572 // Ensure that we are on the correct eLink
573 elinkId = (frame >> 24) & 0x3f;
574 if (elinkId != raw.GetElinkId()) {
575 std::get<1>(result).fNumElinkMis++;
576 }
577
578 // Number of samples indicator = nsamples % 4
579 std::uint8_t nsamplesindicator = (frame >> 18) & 0x3;
580 // Number of required samples as indicated
581 std::uint64_t nreqsamples = (nadcbitstotal + 18) / 9;
582 std::uint8_t nn = nreqsamples % 4;
583 for (std::uint8_t itest = 0; itest < 3; itest++) {
584 if (nn == nsamplesindicator || nreqsamples == 0) break;
585 nreqsamples--;
586 nn = nreqsamples % 4;
587 }
588
589 // There is a chance that the nsamplesindicator bits are corrupted,
590 // here we check that we do not try to extract more adcbits than actually are streamed
591 if (nreqsamples >= isample) {
592 // Now extract from the above values the number of required adc bits from the eom
593 std::int8_t nrequiredbits = (nreqsamples - isample) * 9 - nadcbits;
594 adcbuffer <<= nrequiredbits;
595
596 // The eom carries at maximum 18 adcbits
597 adcbuffer |= static_cast<size_t>((frame & 0x3ffff) >> (18 - nrequiredbits));
598 nadcbits += nrequiredbits;
599
600 while (nadcbits >= 9) {
601 raw.IncNrSamples();
602 raw.SetSample(extractSample(&adcbuffer, &nadcbits), isample);
603 isample++;
604 }
605 }
606 else {
607 std::get<1>(result).fNumCorruptEom++;
608 }
609 std::get<1>(result).fNumCreatedRawMsgs++;
610
611 // the message is done and the raw message container should contain everything we need.
612 // So now we can call makeDigi(). Nevertheless there is a chance for a corrupted message,
613 // which ends up with 0 samples so we have to check for it.
614 if (isample > 0) std::get<0>(result).push_back(makeDigi(raw, ctx));
615 }
616 else {
617 // We move the word counter backwards by one, such that the unexpected message can correctly be digested
618 iword--;
619 std::get<1>(result).fNumMissingEom++;
620 }
621 break;
622 }
624 std::get<1>(result).fNumWildRda++;
625 break;
626 }
628 std::get<1>(result).fNumWildEom++;
629 break;
630 }
632 std::get<1>(result).fNumCreatedInfoMsgs++;
633 digestInfoMsg(frame);
634 break;
635 }
637 // last word in Microslice is 0.
638 if (iword != (nwords - 1) || (istream != (fStreamsPerWord - 1))) {
639 std::get<1>(result).fNumWildNul++;
640 }
641 break;
642 }
644 std::get<1>(result).fNumUnknownWords++;
645 return result;
646 break;
647 }
648 default:
649 // We have varying msg types for different versions of the message format.
650 // Hence, to not produce compiler warnings we have a "default break;" here.
651 break;
652 }
653 }
654 }
655 return result;
656 }
657 // --------------------------------------------------------------------------
658
659} // namespace cbm::algo::trd
#define L_(level)
void SetTriggerType(const eTriggerType triggerType)
Set digi trigger type.
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::tuple< std::vector< Digi_t >, Monitor_t, Aux_t > Result_t
float_t GetBaseline(const std::vector< std::int16_t > *samples) const
Get the Baseline value The digi charge is an unsigned. Hence, we need to get the baseline to 0.
Spadic::MsMessageType getMessageType(const std::uint32_t frame) const
Identify the message type of a given 32bit frame inside a Microslice.
CbmTrdDigi makeDigi(CbmTrdRawMessageSpadic raw, MsContext &ctx) const
Create an actual digi from the raw message.
Spadic::MsInfoType getInfoType(const std::uint32_t frame) const
Identify the InfoType of a 64bit InfoMessage word inside a Microslice.
std::float_t GetMaxAdcValue(const std::vector< std::int16_t > *samples) const
Get the MaxAdc value.
std::int16_t extractSample(size_t *adcbuffer, size_t *nadcbits) const
Extract one adc sample from a given adcbuffer.
CbmTrdRawMessageSpadic makeRaw(const std::uint32_t frame, std::uint16_t criId, std::uint8_t crobId, std::uint16_t elinkId, std::uint8_t istream, MsContext &ctx) const
Create a CbmTrdRawMessageSpadic from the hit message input.
Spadic::MsInfoType digestBufInfoFlags(const std::uint32_t frame) const
Digest the aditional flags stored in the 4 "cccc" bits of the EPO messages.
static CbmTrdDigi::eTriggerType GetDigiTriggerType(Spadic::eTriggerType tt)
Get the Digi Trigger Type from the raw message triggertype.
void digestInfoMsg(const std::uint32_t frame) const
Digest a info message run all default information forwarding from the msg.
std::float_t extractAvgSample(size_t *adcbuffer, size_t *nadcbits) const
Extract the baseline average sample from a given adcbuffer. Depending on the Spadic settings sample-0...
Result_t operator()(const uint8_t *msContent, const fles::MicrosliceDescriptor &msDescr, const uint64_t tTimeslice) const override
Algorithm execution.
std::uint8_t getTsMsb(const std::uint32_t frame, UnpackMonitorData &monitor) const
Get the ts_msb information from the TS_MSB(kEPO) frame. We take the first of the 3 The 3 redundant TS...
void digestMsFlags(const std::uint16_t flags, UnpackMonitorData &monitor) const
Digest the flags of the currently unpacked µSlice.
@ 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.
@ kNeigh
Neighbor trigger.
@ kGlobal
global trigger.
@ kSelf
Self trigger.
@ kSandN
Self and neighbor trigger at the same time.
@ kNUL
Microslice End.
@ kSOM
Start of Message.
@ kEPO
Epoch Marker or TS_MSB depending on the hitmessage version.
@ kEOM
End of Message.
@ kUNK
Unkown Word.
@ kINF
Info Message.
constexpr std::uint8_t BytesPerWord()
TRD Unpacking parameters for one CROB.
std::vector< UnpackElinkPar > fElinkParams
Parameters for each eLink.
TRD Unpacking parameters for one eLink.
std::vector< uint32_t > fChanAddress
CbmTrdAddress for different channels.
uint32_t fAddress
Asic address.
uint64_t fTimeOffset
Time calibration parameter.
std::vector< std::uint8_t > fNrTsMsbVec
Counter for the ts_msb used to reconstruct the time.
size_t fLastFulltime
Time of the last succesful digest hit message.
size_t fMsStartTimeRelCC
Start time of the current µSlice relative to the Timeslice start time in Spadic CC.
Monitoring data for TRD unpacking.
size_t fNumOverflowFlimFlags
counter for inf/error flags from the µSlices
size_t fNumCrcValidFlags
counter for inf/error flags from the µSlices
size_t fNumNonMajorTsMsb
Counter for the ts_msb used to reconstruct the time.
size_t fNumOverflowUserFlags
counter for inf/error flags from the µSlices
size_t fNumDataErrorFlags
counter for inf/error flags from the µSlices