CbmRoot
Loading...
Searching...
No Matches
CbmTrdUnpackAlgoLegacy2020R.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
6
7#include "CbmTrdDigi.h"
8#include "CbmTrdParManager.h"
9#include "CbmTrdParSetAsic.h"
11
12#include <FairTask.h>
13#include <Logger.h>
14
15#include <RtypesCore.h>
16
17#include <cstdint>
18#include <memory>
19#include <string>
20#include <typeinfo>
21#include <utility>
22
24 : CbmTrdUnpackAlgoBaseR("CbmTrdUnpackAlgoLegacy2020R")
25{
26}
27
29
30// ---- GetParContainerRequest ----
31std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>*
32CbmTrdUnpackAlgoLegacy2020R::GetParContainerRequest(std::string geoTag, std::uint32_t runId)
33{
34 // Basepath for default Trd parameter sets (those connected to a geoTag)
35 std::string basepath = Form("%s/trd_%s", fParFilesBasePath.data(), geoTag.data());
36 std::string temppath = "";
37
38 // Digest the runId information in case of runId = 0 we use the default fall back
39 std::string runpath = "";
40 if (runId != 0) {
41 runpath = ".run" + std::to_string(runId);
42 }
43
44 // Get .asic parameter container
45 temppath = basepath + runpath + ".asic" + ".par";
46 fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmTrdParSetAsic>()));
47
48 // Currently we need the ParSetDigi only for the monitor
49 if (fMonitor) {
50 temppath = basepath + runpath + ".digi" + ".par";
51 auto pair = std::make_pair(temppath, std::make_shared<CbmTrdParSetDigi>());
52 fParContVec.emplace_back(pair);
53 }
54
55
56 // We do not want to require the timeshift pars, since the unpacker has to be run without them to extract them. But if it is available we want to use it.
57 // Get timeshift correction parameters, currently only available for run 831
58 if (runId == 831 && geoTag == "mcbm_beam_2020_03") {
59 temppath = Form("%s/mcbm2020_special/CbmMcbm2020TrdTshiftPar_run%d.par", fParFilesBasePath.data(), runId);
60 fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmMcbm2020TrdTshiftPar>()));
61 }
62
63
64 return &fParContVec;
65}
66
67// ---- extractSample ----
68std::int16_t CbmTrdUnpackAlgoLegacy2020R::extractSample(const size_t word, const Spadic::MsMessageType msgType,
69 std::uint32_t isample, bool multihit)
70{
71
72 switch (msgType) {
74 if (isample > 2) {
75 LOG(error) << fName << "::ExtractSample] SOM MSG - Idx " << isample << " Wrong sample index!";
76 return -256;
77 }
78 break;
79 }
81 if (isample < 3 || isample > 31) {
82 LOG(error) << fName << "::ExtractSample] RDA MSG - Idx " << isample << " Wrong sample index!";
83 return -256;
84 }
85 break;
86 }
87 default:
88 LOG(error) << fName << "::ExtractSample] Wrong Message Type!";
89 return -256;
90 break;
91 }
92
93 size_t mask = 0x1FF;
94 auto index = fExtractSampleIndicesVec.at(isample);
95
96 mask = mask << (9 * (6 - index));
97 size_t temp = word & mask;
98 temp = temp >> (6 - index) * 9;
99 if (fSpadic->GetUseBaselineAvg() && (isample == 0) && !(multihit)) {
107 temp = temp >> 2;
108 temp ^= (-0 ^ temp) & (1 << 7);
109 temp ^= (-1 ^ temp) & (1 << 8);
110 }
111 struct {
112 signed int x : 9;
113 } s;
114 int16_t result = s.x = temp;
115 return result;
116}
117
118// ---- extractEpoch ----
120{
121 size_t mask = 0x3FFFFFFF;
122 mask = mask << 32;
123 return ((word & mask) >> 32);
124}
125
126// ---- finishDerived ----
128{
129 LOG(info) << fName << fNrWildRda << " unexpected RDA words and\n " << fNrUnknownWords << " unknown words.";
130}
131
132
133// ---- getInfoType ----
135{
136 size_t mask = 0x000FFFFF;
137
138 if (((msg & mask) >> 18) == 3) // BOM
139 {
141 }
142 if (((msg & mask) >> 17) == 2) // MSB
143 {
145 }
146 if (((msg & mask) >> 17) == 3) // BUF
147 {
149 }
150 if (((msg & mask) >> 17) == 4) // UNU
151 {
153 }
154 if (((msg & mask) >> 17) == 5) // MIS
155 {
157 }
158 else {
159 LOG(error) << fName << "::GetInfoType] unknown type!";
161 }
162}
163
164
165// ---- getMessageType ----
167{
168 if ((msg >> 61) == 1) // SOM 001. ....
169 {
171 }
172 else if ((msg >> 63) == 1) // RDA 1... ....
173 {
175 }
176 else if ((msg >> 62) == 1) // Epoch 01.. ....
177 {
179 }
180 else if ((msg >> 60) == 1) // Spadic Info Message 0001 ....
181 {
183 }
184 else if (msg == 0) // Last Word in a Microslice is 0
185 {
187 }
188 else // not a spadic message
189 {
191 }
192}
193
194// ---- getNrOfRdaWords ----
195std::uint8_t CbmTrdUnpackAlgoLegacy2020R::getNrOfRdaWords(std::uint8_t nsamples)
196{
197 auto nwords = (nsamples + 3) / 7;
198 return nwords > 5 ? 5 : nwords;
199}
200
201// ---- makeRaw ----
202CbmTrdRawMessageSpadic CbmTrdUnpackAlgoLegacy2020R::makeRaw(const size_t word, fles::MicrosliceDescriptor msDesc)
203{
204
206 uint8_t elinkId = 0, chId = 0, crobId = 0;
207 uint16_t criId = msDesc.eq_id;
208 // char crobId = msDesc.crob_id; // TODO this needs to be implemented into microslice! - PR 03.2020
209 uint8_t hitType = 0, nSamples = 0;
210 bool multihit = false;
211 uint16_t timestamp = 0;
212 size_t mask = 0x3F;
213 mask = mask << 55;
214 elinkId = (char) ((word & mask) >> 55);
215 //extract chID
216 mask = 0xF;
217 mask = mask << 51;
218 chId = (char) ((word & mask) >> 51);
219 //extract timestamp
220 mask = 0xFFFF;
221 mask = mask << 35;
222 timestamp = (uint16_t)((word & mask) >> 35);
223 //extract hitType
224 mask = 0x3;
225 mask = mask << 33;
226 hitType = (uint8_t)((word & mask) >> 33);
227 //extract MultiHit
228 mask = 0x1;
229 mask = mask << 32;
230 multihit = (bool) ((word & mask) >> 32);
231 //extract nrSamples
232 mask = 0x1F;
233 mask = mask << 27;
234 nSamples = (uint8_t)((word & mask) >> 27);
235 nSamples += 1; //spadic counts from 0 to 31
236
237 // get the correct fulltime
238 size_t fulltime = timestamp + (fEpoch * fMsLengthCC); // this is in units of clock cycles
239
240
241 // put the first 3 samples, contained in som, into the message.
242 std::vector<std::int16_t> samples = {};
243 for (std::uint32_t isample = 0; isample < nSamples && isample < 3; isample++) {
244 auto adcvalue = extractSample(word, Spadic::MsMessageType::kSOM, isample, multihit);
245 samples.emplace_back(adcvalue);
246 }
247
248 // Create message
249 CbmTrdRawMessageSpadic retval(chId, elinkId, crobId, criId, hitType, nSamples, multihit, fulltime, samples);
250 return retval;
251}
252
254{
255
256 // Extract the trigger type and translate it to the digi enum
257 auto rawTriggerType = static_cast<Spadic::eTriggerType>(raw.GetHitType());
258 auto triggerType = CbmTrdRawToDigiBaseR::GetDigiTriggerType(rawTriggerType);
259
260 // Get the digi error class (dummy for the time being)
261 Int_t errClass = 0;
262
263 // Get the address of the originating spadic
264 size_t spadicHwAddress(0);
265 spadicHwAddress = (raw.GetElinkId()) + (CbmTrdParAsic::kCriIdPosition * raw.GetCriId())
267 Int_t asicAddress(0);
268 auto mapIt = fSpadicAddressMap.find(spadicHwAddress); // check if asic exists
269 if (mapIt == fSpadicAddressMap.end()) {
270 LOG(debug4) << fName
271 << "::makeDigi - No asic address "
272 "found for Spadic hardware address %lu"
273 << spadicHwAddress;
274 return;
275 }
276 asicAddress = mapIt->second;
277
278 // Get the unique module id from the asic address
279 Int_t uniqueModuleId = asicAddress / 1000;
280
281 // GetChannelId per eLink add NSPADICCH / 2 to the second(first) eLink in the case we start with odd(even) eLinks, since, our mapping is based on odd eLinks
282 auto asicChannelId = (raw.GetElinkId() % 2) == fIsFirstChannelsElinkEven
283 ? raw.GetChannelId()
285
286
287 auto padChNr = (fAsicChannelMap.find(asicAddress))->second.at(asicChannelId);
288
289 // Store the full time information to last full-time member for error message handling
290 fLastFulltime = raw.GetFullTime();
291
292 // Get the time information and apply the necessary correction
293 ULong64_t time = raw.GetTime();
294 if (fTimeshiftsParVec) {
295 time = time - fTimeshiftsParVec->at(padChNr);
296 raw.SetTime(time);
297 }
298 time -= fSystemTimeOffset;
299
300 // Set the time relative to the TS start
301 time -= fTsStartTime;
302
303 auto digi = fRTDMethod->MakeDigi(raw.GetSamples(), padChNr, uniqueModuleId, time, triggerType, errClass);
304
305 // Digest the output, i.e. write to return vector and optional pass to the monitor
306 digestOutput(std::move(digi), raw);
307}
308
309// ---- setDerivedTsParameters ----
311{
312 auto timeshiftpair = fTimeshiftsMap.find(itimeslice);
313 if (timeshiftpair != fTimeshiftsMap.end()) {
314 fTimeshiftsParVec = &timeshiftpair->second;
315 }
316 else
317 return false;
318 return true;
319}
320
321// ---- unpack ----
322bool CbmTrdUnpackAlgoLegacy2020R::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice)
323{
324
325
326 bool unpackOk = true;
327
328 auto msdesc = ts->descriptor(icomp, imslice);
329
330 // Get the µslice size in bytes to calculate the number of completed words
331 auto mssize = msdesc.size;
332
333 // Get the number of complete words in the input MS buffer.
334 std::uint32_t msNrWords = mssize / fBytesPerWord;
335
336 const auto mspointer = ts->content(icomp, imslice);
337 const auto mscontent = reinterpret_cast<const size_t*>(mspointer);
338
339 // Loop over all 64bit-Spadic-Words in the current µslice
340 for (std::uint32_t iword = 0; iword < msNrWords; iword++) {
341 // Access the actual word from the pointer
342 auto word = static_cast<size_t>(mscontent[iword]);
343
344 // Get the type of the word
345 auto kWordtype = getMessageType(word);
346
347 switch (kWordtype) {
349 CbmTrdRawMessageSpadic raw = makeRaw(word, msdesc);
350 auto nsamples = raw.GetNrSamples();
352 if (nsamples > 3) {
353 std::uint32_t isample = 3; // first 3 samples are already handled in som
355 for (uint8_t irda = 0; irda < getNrOfRdaWords(nsamples); irda++) {
356 ++iword;
357 word = static_cast<size_t>(mscontent[iword]);
358 auto kAddWordtype = getMessageType(word);
359 if (kAddWordtype != Spadic::MsMessageType::kRDA) {
360 LOG(error) << fName
361 << "::unpack() Incomplete Spadic "
362 "Message! RDA Word missing, Microslice corrupted.";
363 return kFALSE;
364 }
366 for (std::uint32_t iwordsample = 0; isample < nsamples && iwordsample < 7; isample++, iwordsample++) {
367 auto adcvalue = extractSample(word, kAddWordtype, isample);
368 raw.SetSample(adcvalue, isample);
369 }
370 }
371 }
372 ++fNrCreatedRawMsgs;
373
374 // Message is completed here. Now lets Generate the digi and save raw message if needed.
375 makeDigi(raw);
376
377 break;
378 }
380 // All rda words should be handled inside the kSOM case. Hence, this case should not appear and we have to count it as an error appearance.
381 LOG(error) << fName
382 << "::unpack() Unexpected RDA "
383 "Word. Microslice corrupted.";
384 fNrWildRda++;
385 return false;
386 break;
387 }
390 if (fOptOutBVec) {
391 fOptOutBVec->emplace_back(std::make_pair(fLastFulltime, word));
392 }
393 fNrCreatedInfoMsgs++;
394 // TODO here we also want to call the monitoring class
395 // Spadic::MsInfoType infoType = getInfoType(word);
396 // "Spadic_Info_Types";
397 // if (fIsActiveHistoVec[kSpadic_Info_Types]) {
398 // ((TH2I*) fHistoArray.At(kSpadic_Info_Types))->Fill(fLastFulltime, (Int_t) infoType);
399 // }
400 break;
401 }
403 if (iword != (msNrWords - 1)) // last word in Microslice is 0.
404 {
405 LOG(error) << fName
406 << "::unpack() Null Word but "
407 "not at end of Microslice.";
408 }
409 break;
410 }
412 LOG(error) << fName
413 << "::unpack() Unknown Word. "
414 "Microslice corrupted.";
416 return false;
417 break;
418 }
420 fEpoch = extractEpoch(word);
421 fNrEpochMsgs++;
422 break;
423 }
424 default:
425 // We have varying msg types for different versions of the message format. Hence, to not produce compiler warnings we have a "default break;" here.
426 break;
427 }
428 }
429 return unpackOk;
430}
431
ClassImp(CbmConverterManager)
Assign pad layout to TRD Modules.
Unpacker algorithms for the TrdR 2020 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
void SetTime(double setvalue)
const std::vector< std::int16_t > * GetSamples() const
std::uint8_t GetChannelId() const
void SetSample(std::int16_t value, std::uint8_t pos)
std::uint8_t GetNrSamples() const
std::uint8_t GetCrobId() const
std::uint8_t GetHitType() const
std::uint8_t GetElinkId() const
std::uint16_t GetCriId() const
static CbmTrdDigi::eTriggerType GetDigiTriggerType(Spadic::eTriggerType tt)
Get the Digi Trigger Type from the raw message triggertype.
static UInt_t GetNrChannels()
std::shared_ptr< CbmTrdRawToDigiBaseR > fRTDMethod
raw to digi extraction method, set in the task
std::map< Int_t, std::vector< Int_t > > fAsicChannelMap
Map to retrieve module channelId from asicAddress and asicChannel.
void digestOutput(std::unique_ptr< CbmTrdDigi > digi, CbmTrdRawMessageSpadic raw)
Handle the output created by the explicit algorithms. E.g. write to output vectors.
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.
Bool_t fIsFirstChannelsElinkEven
Define if the first 16 channels (00..15) are found on the even (set true) or odd (false) eLinkId....
std::map< size_t, Int_t > fSpadicAddressMap
Map to retrieve asic address from CriId/CrobId/ElinkId (see CbmTrdHardwareSetupR)
std::map< size_t, std::vector< Int_t > > fTimeshiftsMap
Map containing the timeshift parameters for the correction of the µSlice timeshifts....
std::uint8_t getNrOfRdaWords(std::uint8_t nsamples)
Get the Nr Of Rda Words required for the amount of ADC samples.
size_t fMsLengthCC
Microslice length [CC]. To be overwritten in the version specific unpackers.
Spadic::MsInfoType getInfoType(const size_t msg)
Identify the InfoType of a 64bit InfoMessage word inside a Microslice.
virtual bool unpack(const fles::Timeslice *ts, std::uint16_t icomp, UInt_t imslice)
Unpack a given microslice.
void makeDigi(CbmTrdRawMessageSpadic raw)
Create an actual digi from the raw message.
CbmTrdUnpackAlgoLegacy2020R()
Create the Cbm Trd Unpack AlgoBase object.
std::vector< std::int32_t > * fTimeshiftsParVec
Vector containing the timeshift parameters for the correction of the µSlice timeshifts for a given ts...
Spadic::MsMessageType getMessageType(const size_t msg)
Identify the message type of a 64bit word inside a Microslice.
size_t extractEpoch(const size_t word)
Extract the epoch time reference information from the epoch word.
static const std::uint8_t fBytesPerWord
Bytes per word stored in the microslices.
size_t fEpoch
Time of the current epoch marker.
std::int16_t extractSample(const size_t word, const Spadic::MsMessageType msgType, std::uint32_t isample, bool multihit=false)
Extract the given sample from the given rda word.
const std::vector< std::uint8_t > fExtractSampleIndicesVec
virtual CbmTrdRawMessageSpadic makeRaw(const size_t word, fles::MicrosliceDescriptor msDesc)
Create a CbmTrdRawMessageSpadic from the hit message input.
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...
virtual bool setDerivedTsParameters(size_t itimeslice)
Set the Derived Ts Parameters.
virtual ~CbmTrdUnpackAlgoLegacy2020R()
Destroy the Cbm Trd Unpack Task object.
void finishDerived()
Additional explicit finish function of this algo implementation.
@ kUNU
Unused request. 100. .... .... .... cccc.
@ kBOM
Buffer overflow count. 11nn nnnn nnnn nnnn cccc.
@ kMIS
Missing request. 101. .... .... .... ....
@ kBUF
Buffer full. 011b b... .... .... cccc.
@ kMSB
Message build error. 010. .... .... .... cccc.
@ kNUL
Microslice End.
@ kSOM
Start of Message.
@ kEPO
Epoch Marker or TS_MSB depending on the hitmessage version.
@ kUNK
Unkown Word.
@ kINF
Info Message.