]> git.uio.no Git - u/mrichter/AliRoot.git/blame_incremental - TRD/AliTRDrawStream.cxx
Fixing more coverity
[u/mrichter/AliRoot.git] / TRD / AliTRDrawStream.cxx
... / ...
CommitLineData
1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16////////////////////////////////////////////////////////////////////////////
17// //
18// Decoding data from the TRD raw stream //
19// and translation into ADC values, on-line tracklets and tracks //
20// //
21// Author: J. Klein (jochen.klein@cern.ch) //
22// //
23////////////////////////////////////////////////////////////////////////////
24
25#include <cstdio>
26#include <cstdarg>
27
28#include "TClonesArray.h"
29#include "TTree.h"
30
31#include "AliLog.h"
32#include "AliRawReader.h"
33#include "AliTRDdigitsManager.h"
34#include "AliTRDdigitsParam.h"
35#include "AliTRDtrapConfig.h"
36#include "AliTRDarrayADC.h"
37#include "AliTRDarrayDictionary.h"
38#include "AliTRDSignalIndex.h"
39#include "AliTRDtrackletWord.h"
40#include "AliTRDtrackletMCM.h"
41#include "AliESDTrdTrack.h"
42#include "AliTreeLoader.h"
43#include "AliLoader.h"
44
45#include "AliTRDrawStream.h"
46
47// temporary
48#include "AliRunLoader.h"
49
50ClassImp(AliTRDrawStream)
51
52// some static information
53Int_t AliTRDrawStream::fgMcmOrder[] = {12, 13, 14, 15,
54 8, 9, 10, 11,
55 4, 5, 6, 7,
56 0, 1, 2, 3};
57Int_t AliTRDrawStream::fgRobOrder [] = {0, 1, 2, 3};
58const Int_t AliTRDrawStream::fgkNlinks = 12;
59const Int_t AliTRDrawStream::fgkNstacks = 5;
60const Int_t AliTRDrawStream::fgkNsectors = 18;
61const Int_t AliTRDrawStream::fgkNtriggers = 12;
62const UInt_t AliTRDrawStream::fgkDataEndmarker = 0x00000000;
63const UInt_t AliTRDrawStream::fgkTrackletEndmarker = 0x10001000;
64const UInt_t AliTRDrawStream::fgkStackEndmarker[] = { 0xe0d01000, 0xe0d10000 };
65
66const char* AliTRDrawStream::fgkErrorMessages[] = {
67 "Unknown error",
68 "Link monitor active",
69 "Event counter mismatch",
70 "not a TRD equipment (1024-1041)",
71 "Invalid Stack header",
72 "Invalid detector number",
73 "No digits could be retrieved from the digitsmanager",
74 "HC header mismatch",
75 "HC check bits wrong",
76 "Unexpected position in readout stream",
77 "Invalid testpattern mode",
78 "Testpattern mismatch",
79 "Number of timebins changed",
80 "ADC mask inconsistent",
81 "ADC check bits invalid",
82 "Missing ADC data",
83 "Missing expected ADC channels",
84 "Missing MCM headers",
85 "Missing TP data",
86 "CRC mismatch"
87};
88
89Int_t AliTRDrawStream::fgErrorDebugLevel[] = {
90 0,
91 0,
92 2,
93 1,
94 0,
95 1,
96 1,
97 1,
98 1,
99 2,
100 1,
101 0,
102 1,
103 1,
104 2,
105 1,
106 1,
107 1,
108 0,
109 0
110};
111
112AliTRDrawStream::ErrorBehav_t AliTRDrawStream::fgErrorBehav[] = {
113 AliTRDrawStream::kTolerate,
114 AliTRDrawStream::kDiscardHC,
115 AliTRDrawStream::kTolerate,
116 AliTRDrawStream::kAbort,
117 AliTRDrawStream::kAbort,
118 AliTRDrawStream::kAbort,
119 AliTRDrawStream::kAbort,
120 AliTRDrawStream::kDiscardHC,
121 AliTRDrawStream::kDiscardHC,
122 AliTRDrawStream::kTolerate,
123 AliTRDrawStream::kTolerate,
124 AliTRDrawStream::kTolerate,
125 AliTRDrawStream::kTolerate,
126 AliTRDrawStream::kTolerate,
127 AliTRDrawStream::kTolerate,
128 AliTRDrawStream::kTolerate,
129 AliTRDrawStream::kTolerate,
130 AliTRDrawStream::kTolerate,
131 AliTRDrawStream::kTolerate,
132 AliTRDrawStream::kTolerate
133};
134
135AliTRDrawStream::AliTRDrawStream(AliRawReader *rawReader) :
136 fStoreError(&AliTRDrawStream::ForgetError),
137 fRawReader(rawReader),
138 fDigitsManager(0x0),
139 fDigitsParam(0x0),
140 fErrors(0x0),
141 fLastError(),
142 fErrorFlags(0),
143 fStats(),
144 fPayloadStart(0x0),
145 fPayloadCurr(0x0),
146 fPayloadSize(0),
147 fNtimebins(-1),
148 fLastEvId(-1),
149 fCurrSlot(-1),
150 fCurrLink(-1),
151 fCurrRobPos(-1),
152 fCurrMcmPos(-1),
153 fCurrEquipmentId(0),
154 fCurrSmHeaderSize(0),
155 fCurrSmHeaderVersion(0),
156 fCurrTrailerReadout(0),
157 fCurrTrgHeaderAvail(0),
158 fCurrTrgHeaderReadout(0),
159 fCurrTrkHeaderAvail(0),
160 fCurrStackEndmarkerAvail(0),
161 fCurrEvType(0),
162 fCurrTriggerEnable(0),
163 fCurrTriggerFired(0),
164 fCurrTrackEnable(0),
165 fCurrTrackletEnable(0),
166 fCurrStackMask(0),
167 fCurrTrkHeaderIndexWord(0x0),
168 fCurrTrkHeaderSize(0x0),
169 fCurrTrkFlags(0x0),
170 fCurrTrgHeaderIndexWord(0x0),
171 fCurrTrgHeaderSize(0x0),
172 fCurrTrgFlags(0x0),
173 fCurrStackIndexWord(0x0),
174 fCurrStackHeaderSize(0x0),
175 fCurrStackHeaderVersion(0x0),
176 fCurrLinkMask(0x0),
177 fCurrCleanCheckout(0x0),
178 fCurrBoardId(0x0),
179 fCurrHwRev(-1),
180 fCurrHwRevTMU(0x0),
181 fCurrLinkMonitorFlags(0x0),
182 fCurrLinkDataTypeFlags(0x0),
183 fCurrLinkDebugFlags(0x0),
184 fCurrMatchFlagsSRAM(0),
185 fCurrMatchFlagsPostBP(0),
186 fCurrChecksumStack(),
187 fCurrChecksumSIU(0),
188 fCurrSpecial(-1),
189 fCurrMajor(-1),
190 fCurrMinor(-1),
191 fCurrAddHcWords(-1),
192 fCurrSm(-1),
193 fCurrStack(-1),
194 fCurrLayer(-1),
195 fCurrSide(-1),
196 fCurrHC(-1),
197 fCurrCheck(-1),
198 fCurrNtimebins(-1),
199 fCurrBC(-1),
200 fCurrPtrgCnt(-1),
201 fCurrPtrgPhase(-1),
202 fNDumpMCMs(0),
203 fTrackletArray(0x0),
204 fAdcArray(0x0),
205 fSignalIndex(0x0),
206 fTrackletTree(0x0),
207 fTracklets(0x0),
208 fTracks(0x0),
209 fMarkers(0x0)
210{
211 // default constructor
212
213 fCurrTrkHeaderIndexWord = new UInt_t[fgkNstacks];
214 fCurrTrkHeaderSize = new UInt_t[fgkNstacks];
215 fCurrTrkFlags = new ULong64_t[fgkNsectors*fgkNstacks];
216 fCurrTrgHeaderIndexWord = new UInt_t[fgkNtriggers];
217 fCurrTrgHeaderSize = new UInt_t[fgkNtriggers];
218 fCurrTrgFlags = new UInt_t[fgkNsectors];
219 fCurrStackIndexWord = new UInt_t[fgkNstacks];
220 fCurrStackHeaderSize = new UInt_t[fgkNstacks];
221 fCurrStackHeaderVersion = new UInt_t[fgkNstacks];
222 fCurrLinkMask = new UInt_t[fgkNstacks];
223 fCurrCleanCheckout = new UInt_t[fgkNstacks];
224 fCurrBoardId = new UInt_t[fgkNstacks];
225 fCurrHwRevTMU = new UInt_t[fgkNstacks];
226 fCurrLinkMonitorFlags = new UInt_t[fgkNstacks * fgkNlinks];
227 fCurrLinkDataTypeFlags = new UInt_t[fgkNstacks * fgkNlinks];
228 fCurrLinkDebugFlags = new UInt_t[fgkNstacks * fgkNlinks];
229 for (Int_t iSector = 0; iSector < fgkNsectors; iSector++)
230 fCurrTrgFlags[iSector] = 0;
231 for (Int_t i = 0; i < 100; i++)
232 fDumpMCM[i] = 0;
233
234 // preparing TClonesArray
235 fTrackletArray = new TClonesArray("AliTRDtrackletWord", 256);
236
237 // setting up the error tree
238 fErrors = new TTree("errorStats", "Error statistics");
239 fErrors->SetDirectory(0x0);
240 fErrors->Branch("error", &fLastError);
241 fErrors->SetCircular(1000);
242 for (Int_t i = 0; i < 100; i++) {
243 fErrorBuffer[i] = 0;
244 }
245
246}
247
248AliTRDrawStream::~AliTRDrawStream()
249{
250 // destructor
251
252 delete fErrors;
253
254 delete [] fCurrTrkHeaderIndexWord;
255 delete [] fCurrTrkHeaderSize;
256 delete [] fCurrTrkFlags;
257 delete [] fCurrTrgHeaderIndexWord;
258 delete [] fCurrTrgHeaderSize;
259 delete [] fCurrTrgFlags;
260 delete [] fCurrStackIndexWord;
261 delete [] fCurrStackHeaderSize;
262 delete [] fCurrStackHeaderVersion;
263 delete [] fCurrLinkMask;
264 delete [] fCurrCleanCheckout;
265 delete [] fCurrBoardId;
266 delete [] fCurrHwRevTMU;
267 delete [] fCurrLinkMonitorFlags;
268 delete [] fCurrLinkDataTypeFlags;
269 delete [] fCurrLinkDebugFlags;
270}
271
272Bool_t AliTRDrawStream::ReadEvent(TTree *trackletTree)
273{
274 // read the current event from the raw reader and fill it to the digits manager
275
276 if (!fRawReader) {
277 AliError("No raw reader available");
278 return kFALSE;
279 }
280
281 // tracklet output
282 ConnectTracklets(trackletTree);
283
284 // some preparations
285 fDigitsParam = 0x0;
286
287 // loop over all DDLs
288 // data starts with GTU payload, i.e. SM index word
289 UChar_t *buffer = 0x0;
290
291 while (fRawReader->ReadNextData(buffer)) {
292
293 fCurrEquipmentId = fRawReader->GetEquipmentId();
294 AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
295
296 if (fCurrEquipmentId < kDDLOffset || fCurrEquipmentId > kDDLMax) {
297 EquipmentError(kNonTrdEq, "Skipping");
298 continue;
299 }
300
301 if (fMarkers)
302 new ((*fMarkers)[fMarkers->GetEntriesFast()])
303 AliTRDrawStreamError(-kSecactive, fCurrEquipmentId - kDDLOffset);
304
305 ReadGTUHeaders((UInt_t*) buffer);
306
307 if (fCurrTrailerReadout)
308 ReadGTUTrailer();
309
310 // loop over all active links
311 AliDebug(2, Form("Stack mask 0x%02x", fCurrStackMask));
312 for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
313 fCurrSlot = iStack;
314 if ((fCurrStackMask & (1 << fCurrSlot)) == 0)
315 continue;
316
317 AliDebug(2, Form("Stack %i, Link mask: 0x%02x", fCurrSlot, fCurrLinkMask[fCurrSlot]));
318 for (Int_t iLink = 0; iLink < fgkNlinks; iLink++) {
319 fCurrLink = iLink;
320 fCurrHC = (fCurrEquipmentId - kDDLOffset) * fgkNstacks * fgkNlinks +
321 fCurrSlot * fgkNlinks + iLink;
322 if ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) == 0)
323 continue;
324
325 Int_t size = 0;
326
327 fErrorFlags = 0;
328 // check for link monitor error flag
329 if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0) {
330 LinkError(kLinkMonitor);
331 if (fgErrorBehav[kLinkMonitor] == kTolerate)
332 size += ReadLinkData();
333 }
334 else
335 // read the data from one HC
336 size += ReadLinkData();
337
338 // read all data endmarkers
339 size += SeekNextLink();
340 }
341
342 // continue with next stack
343 SeekNextStack();
344 }
345 }
346
347 return kTRUE;
348}
349
350
351Bool_t AliTRDrawStream::NextDDL()
352{
353 // continue reading with the next equipment
354
355 if (!fRawReader)
356 return kFALSE;
357
358 fCurrEquipmentId = 0;
359 fCurrSlot = 0;
360 fCurrLink = 0;
361
362 UChar_t *buffer = 0x0;
363
364 while (fRawReader->ReadNextData(buffer)) {
365
366 fCurrEquipmentId = fRawReader->GetEquipmentId();
367 AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
368
369 if (fCurrEquipmentId < kDDLOffset || fCurrEquipmentId > kDDLMax) {
370 EquipmentError(kNonTrdEq, "Skipping");
371 continue;
372 }
373
374 if (fMarkers)
375 new ((*fMarkers)[fMarkers->GetEntriesFast()])
376 AliTRDrawStreamError(-kSecactive, fCurrEquipmentId - kDDLOffset);
377
378 ReadGTUHeaders((UInt_t*) buffer);
379
380 if (fCurrTrailerReadout)
381 ReadGTUTrailer();
382
383 return kTRUE;
384 }
385
386 return kFALSE;
387}
388
389
390Int_t AliTRDrawStream::NextChamber(AliTRDdigitsManager *digMgr)
391{
392 // read the data for the next chamber
393 // in case you only want to read the data of a single chamber
394 // to read all data ReadEvent(...) is recommended
395
396 fDigitsManager = digMgr;
397 fDigitsParam = 0x0;
398
399 fErrorFlags = 0;
400
401 // tracklet output preparation
402 TTree *trklTree = 0x0;
403 AliRunLoader *rl = AliRunLoader::Instance();
404 AliLoader* trdLoader = rl ? rl->GetLoader("TRDLoader") : NULL;
405 AliDataLoader *trklLoader = trdLoader ? trdLoader->GetDataLoader("tracklets") : NULL;
406 if (trklLoader) {
407 AliTreeLoader *trklTreeLoader = (AliTreeLoader*) trklLoader->GetBaseLoader("tracklets-raw");
408 if (trklTreeLoader)
409 trklTree = trklTreeLoader->Tree();
410 else
411 trklTree = trklLoader->Tree();
412 }
413
414 if (fTrackletTree != trklTree)
415 ConnectTracklets(trklTree);
416
417 if (!fRawReader) {
418 AliError("No raw reader available");
419 return -1;
420 }
421
422 while (fCurrSlot < 0 || fCurrSlot >= fgkNstacks) {
423 if (!NextDDL()) {
424 fCurrSlot = -1;
425 return -1;
426 }
427 while ((fCurrSlot < fgkNstacks) &&
428 (((fCurrStackMask & (1 << fCurrSlot)) == 0) ||
429 ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0)) {
430 fCurrLink++;
431 if (fCurrLink >= fgkNlinks) {
432 fCurrLink = 0;
433 fCurrSlot++;
434 }
435 }
436 }
437
438 AliDebug(2, Form("Stack %i, Link %i, mask: 0x%02x", fCurrSlot, fCurrLink, fCurrLinkMask[fCurrSlot]));
439 fCurrHC = (fCurrEquipmentId - kDDLOffset) * fgkNlinks * fgkNstacks +
440 fCurrSlot * fgkNlinks + fCurrLink;
441
442 if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0) {
443 LinkError(kLinkMonitor);
444 if (fgErrorBehav[kLinkMonitor] == kTolerate)
445 ReadLinkData();
446 }
447 else
448 // read the data from one HC
449 ReadLinkData();
450
451 // read all data endmarkers
452 SeekNextLink();
453
454 if (fCurrLink % 2 == 0) {
455 // if we just read the A-side HC then also check the B-side
456 fCurrLink++;
457 fCurrHC++;
458 if (fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) {
459 if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0) {
460 LinkError(kLinkMonitor);
461 if (fgErrorBehav[kLinkMonitor] == kTolerate)
462 ReadLinkData();
463 }
464 else {
465 ReadLinkData();
466 }
467 SeekNextLink();
468 }
469 }
470
471 do {
472 if ((fCurrStackMask & (1 << fCurrSlot)) == 0) {
473 fCurrLink = 0;
474 fCurrSlot++;
475 }
476 else {
477 fCurrLink++;
478 if (fCurrLink >= fgkNlinks) {
479 SeekNextStack();
480 fCurrLink = 0;
481 fCurrSlot++;
482 }
483 }
484 } while ((fCurrSlot < fgkNstacks) &&
485 (((fCurrStackMask & (1 << fCurrSlot)) == 0) ||
486 ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0));
487
488 // return chamber information from HC if it is valid
489 // otherwise return information from link position
490 if (fCurrSm < 0 || fCurrSm >= fgkNsectors || fCurrStack < 0 || fCurrStack >= fgkNstacks || fCurrLayer < 0 || fCurrLayer >= fgkNlinks/2)
491 return ((fCurrEquipmentId-kDDLOffset) + fCurrSlot * fgkNlinks/2 + fCurrLink/2);
492 else
493 return (fCurrSm * fgkNstacks*fgkNlinks/2 + fCurrStack * fgkNlinks/2 + fCurrLayer);
494}
495
496
497Int_t AliTRDrawStream::ReadGTUHeaders(UInt_t *buffer)
498{
499 // check the data source and read the headers
500
501 if (fCurrEquipmentId >= kDDLOffset && fCurrEquipmentId <= kDDLMax) {
502 // this is ROC data
503
504 // setting the pointer to data and current reading position
505 fPayloadCurr = fPayloadStart = buffer;
506 fPayloadSize = fRawReader->GetDataSize() / sizeof(UInt_t);
507 fStats.fStatsSector[fCurrEquipmentId - kDDLOffset].fBytes = fRawReader->GetDataSize();
508 AliDebug(2, Form("Read buffer of size: %i", fRawReader->GetDataSize()));
509
510 AliDebug(1, DumpRaw("raw data", fPayloadCurr, TMath::Min(fPayloadSize, 1000)));
511
512 // read SM header
513 if (ReadSmHeader() < 0) {
514 AliError(Form("Reading SM header failed, skipping this DDL %i", fCurrEquipmentId));
515 return -1;
516 }
517
518 // read tracking headers (if available)
519 if (fCurrTrkHeaderAvail) {
520 for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
521 if ((fCurrStackMask & (1 << iStack)) != 0)
522 ReadTrackingHeader(iStack);
523 }
524 }
525
526 // read trigger header(s) (if available)
527 if (fCurrTrgHeaderAvail)
528 ReadTriggerHeaders();
529
530 // read stack header
531 for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
532 if ((fCurrStackMask & (1 << iStack)) != 0)
533 ReadStackHeader(iStack);
534 }
535
536 return 0;
537 }
538 else
539 return -1;
540}
541
542Int_t AliTRDrawStream::ReadSmHeader()
543{
544 // read the SMU index header at the current reading position
545 // and store the information in the corresponding variables
546
547 if (fPayloadCurr - fPayloadStart >= fPayloadSize - 1) {
548 EquipmentError(kUnknown, "SM Header incomplete");
549 return -1;
550 }
551
552 fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] = 0;
553
554 fCurrSmHeaderSize = ((*fPayloadCurr) >> 16) & 0xffff;
555 fCurrSmHeaderVersion = ((*fPayloadCurr) >> 12) & 0xf;
556 fCurrTrackEnable = ((*fPayloadCurr) >> 6) & 0x1;
557 fCurrTrackletEnable = ((*fPayloadCurr) >> 5) & 0x1;
558 fCurrStackMask = ((*fPayloadCurr) ) & 0x1f;
559 fCurrHwRev = (fPayloadCurr[1] >> 12) & 0xffff;
560 fCurrStackEndmarkerAvail = 0;
561
562 switch (fCurrSmHeaderVersion) {
563 case 0xb:
564 fCurrTrailerReadout = 0;
565 fCurrTrgHeaderAvail = 0;
566 fCurrEvType = 0;
567 fCurrTrkHeaderAvail = 0;
568
569 DecodeGTUtracks();
570 break;
571
572 case 0xc:
573 fCurrTrailerReadout = ((*fPayloadCurr) >> 10) & 0x1;
574 fCurrTrgHeaderAvail = 1;
575 fCurrTrgHeaderReadout = ((*fPayloadCurr) >> 9) & 0x1;
576 fCurrEvType = ((*fPayloadCurr) >> 7) & 0x3;
577 fCurrTrkHeaderAvail = fCurrTrackEnable;
578 fCurrTriggerEnable = (fPayloadCurr[2] >> 8) & 0xfff;
579 fCurrTriggerFired = (fPayloadCurr[2] >> 20) & 0xfff;
580 fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] = fCurrTriggerFired;
581 break;
582
583 case 0xd:
584 fCurrTrailerReadout = ((*fPayloadCurr) >> 10) & 0x1;
585 fCurrTrgHeaderAvail = 1;
586 fCurrTrgHeaderReadout = ((*fPayloadCurr) >> 9) & 0x1;
587 fCurrEvType = ((*fPayloadCurr) >> 7) & 0x3;
588 fCurrTrkHeaderAvail = fCurrTrackEnable;
589 fCurrTriggerEnable = (fPayloadCurr[2] >> 8) & 0xfff;
590 fCurrTriggerFired = (fPayloadCurr[2] >> 20) & 0xfff;
591 fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] = fCurrTriggerFired;
592 fCurrStackEndmarkerAvail = 1;
593 break;
594
595 default:
596 AliError(Form("unknown SM header version: 0x%x", fCurrSmHeaderVersion));
597 }
598
599 AliDebug(5, Form("SM header: size: %i, version: %i, track enable: %i, tracklet enable: %i, stack mask: %2x, trailer: %i, trgheader: %i, trkheader: %i",
600 fCurrSmHeaderSize,
601 fCurrSmHeaderVersion,
602 fCurrTrackEnable,
603 fCurrTrackletEnable,
604 fCurrStackMask,
605 fCurrTrailerReadout,
606 fCurrTrgHeaderAvail,
607 fCurrTrkHeaderAvail ));
608
609 // jump to the first word after the SM header
610 fPayloadCurr += fCurrSmHeaderSize + 1;
611
612 return fCurrSmHeaderSize + 1;
613}
614
615Int_t AliTRDrawStream::DecodeGTUtracks()
616{
617 // decode GTU track words
618 // this depends on the hardware revision of the SMU
619
620 Int_t sector = fCurrEquipmentId-kDDLOffset;
621
622 if ((sector < 0) || (sector > 17)) {
623 AliError(Form("Invalid sector %i for GTU tracks", sector));
624 return -1;
625 }
626
627 AliDebug(1, DumpRaw(Form("GTU tracks in sector %2i (hw rev %i)", sector, fCurrHwRev),
628 fPayloadCurr + 4, 10, 0xffe0ffff));
629
630 fCurrTrgFlags[sector] = 0;
631
632 if (fCurrHwRev < 1772) {
633 UInt_t fastWord; // fast trigger word
634 ULong64_t trackWord = 0; // extended track word
635 Int_t stack = 0;
636 Int_t idx = 0;
637 for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
638 if (fPayloadCurr[iWord] == 0x10000000) { // stack boundary marker
639 stack++;
640 idx = 0;
641 }
642 else {
643 if ((idx == 0) &&
644 ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
645 fastWord = fPayloadCurr[iWord];
646 fCurrTrgFlags[sector] |= 1 << (stack+11); // assume tracking done if fast word sent
647 AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
648 continue;
649 }
650 else if ((idx & 0x1) == 0x1) {
651 trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
652 AliDebug(1,Form("track debug word: 0x%016llx", trackWord));
653 if (fTracks) {
654 AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
655 AliESDTrdTrack();
656
657 trk->SetSector(sector);
658 trk->SetStack((trackWord >> 60) & 0x7);
659 trk->SetA(0);
660 trk->SetB(0);
661 trk->SetPID(0);
662 trk->SetLayerMask((trackWord >> 16) & 0x3f);
663 trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
664 trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
665 trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
666 trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
667 trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
668 trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
669
670 trk->SetFlags(0);
671 trk->SetReserved(0);
672 trk->SetLabel(-3);
673
674 Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
675 if (TMath::Abs(pt) > 0.1) {
676 trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
677 }
678 }
679 }
680 else {
681 trackWord = fPayloadCurr[iWord];
682 }
683 idx++;
684 }
685 }
686 }
687 else if (fCurrHwRev < 1804) {
688 UInt_t fastWord; // fast trigger word
689 ULong64_t trackWord = 0; // extended track word
690 Int_t stack = 0;
691 Int_t idx = 0;
692 for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
693 if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
694 stack++;
695 idx = 0;
696 }
697 else {
698 if ((idx == 0) &&
699 ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
700 fastWord = fPayloadCurr[iWord];
701 fCurrTrgFlags[sector] |= 1 << (stack+11); // assume tracking done if fast word sent
702 AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
703 continue;
704 }
705 else if ((idx & 0x1) == 0x1) {
706 trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
707 AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
708 if (fTracks) {
709 AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
710 AliESDTrdTrack();
711
712 trk->SetSector(fCurrEquipmentId-kDDLOffset);
713 trk->SetStack((trackWord >> 60) & 0x7);
714 trk->SetA(0);
715 trk->SetB(0);
716 trk->SetPID(0);
717 trk->SetLayerMask((trackWord >> 16) & 0x3f);
718 trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
719 trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
720 trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
721 trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
722 trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
723 trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
724
725 trk->SetFlags(0);
726 trk->SetReserved(0);
727 trk->SetLabel(-3);
728
729 Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
730 if (TMath::Abs(pt) > 0.1) {
731 trk->SetA((Int_t) (-0.15*51625./100./pt / 160e-4 * 2));
732 }
733 }
734 }
735 else {
736 trackWord = fPayloadCurr[iWord];
737 }
738 idx++;
739 }
740 }
741 }
742 else if (fCurrHwRev < 1819) {
743 UInt_t fastWord; // fast trigger word
744 ULong64_t trackWord = 0; // extended track word
745 Int_t stack = 0;
746 Int_t idx = 0;
747 for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
748 if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
749 stack++;
750 idx = 0;
751 }
752 else {
753 if ((idx == 0) &&
754 ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
755 fastWord = fPayloadCurr[iWord];
756 if (fastWord & (1 << 13))
757 fCurrTrgFlags[sector] |= 1 << (stack+11);
758 AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
759 continue;
760 }
761 else if ((idx & 0x1) == 0x1) {
762 trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
763 AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
764
765 if (fTracks) {
766 AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
767 AliESDTrdTrack();
768
769 trk->SetSector(fCurrEquipmentId-kDDLOffset);
770 trk->SetStack((trackWord >> 60) & 0x7);
771 trk->SetA(0);
772 trk->SetB(0);
773 // trk->SetPt(((trackWord & 0xffff) ^ 0x8000) - 0x8000);
774 trk->SetPID(0);
775 trk->SetLayerMask((trackWord >> 16) & 0x3f);
776 trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
777 trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
778 trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
779 trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
780 trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
781 trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
782
783 trk->SetFlags(0);
784 trk->SetReserved(0);
785 trk->SetLabel(-3);
786
787 Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
788 if (TMath::Abs(pt) > 0.1) {
789 trk->SetA((Int_t) (0.15*51625./100./trk->Pt() / 160e-4 * 2));
790 }
791 }
792 }
793 else {
794 trackWord = fPayloadCurr[iWord];
795 }
796 idx++;
797 }
798 }
799 }
800 else if (fCurrHwRev < 1860) {
801 UInt_t fastWord; // fast trigger word
802 ULong64_t trackWord = 0; // extended track word
803 Int_t stack = 0;
804 Int_t idx = 0;
805 Bool_t upperWord = kFALSE;
806 Int_t word = 0;
807 for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
808 if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
809 stack++;
810 idx = 0;
811 upperWord = kFALSE;
812 }
813 else {
814 // assemble the 32-bit words out of 16-bit blocks
815 if (upperWord) {
816 word |= (fPayloadCurr[iWord] & 0xffff0000);
817 upperWord = kFALSE;
818 }
819 else {
820 // lower word is read first
821 word = (fPayloadCurr[iWord] & 0xffff0000) >> 16;
822 upperWord = kTRUE;
823 continue;
824 }
825
826 if ((word & 0xffff0008) == 0x13370008) {
827 fastWord = word;
828 AliDebug(1, Form("stack %i: fast track word: 0x%08x", stack, fastWord));
829 if (fastWord & (1 << 13))
830 fCurrTrgFlags[sector] |= 1 << (stack+11);
831 continue;
832 }
833 else if ((idx & 0x1) == 0x1) {
834 trackWord |= ((ULong64_t) word) << 32;
835 AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
836 if (fTracks) {
837 AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
838 AliESDTrdTrack();
839
840 trk->SetSector(fCurrEquipmentId-kDDLOffset);
841 trk->SetStack((trackWord >> 60) & 0x7);
842 trk->SetA(0);
843 trk->SetB(0);
844 trk->SetPID(0);
845 trk->SetLayerMask((trackWord >> 16) & 0x3f);
846 trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
847 trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
848 trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
849 trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
850 trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
851 trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
852
853 trk->SetFlags(0);
854 trk->SetReserved(0);
855 trk->SetLabel(-3);
856
857 Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
858 if (TMath::Abs(pt) > 0.1) {
859 trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
860 }
861 }
862 }
863 else {
864 trackWord = word;
865 }
866 idx++;
867 }
868 }
869
870 }
871 else {
872 ULong64_t trackWord = 0; // this is the debug word
873 Int_t stack = 0;
874 Int_t idx = 0;
875 Bool_t upperWord = kFALSE;
876 Int_t word = 0;
877 for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
878 if (fPayloadCurr[iWord] == 0xffe0ffff) {
879 stack++;
880 idx = 0;
881 upperWord = kFALSE;
882 }
883 else {
884 // assemble the 32-bit words out of 16-bit blocks
885 if (upperWord) {
886 word |= (fPayloadCurr[iWord] & 0xffff0000);
887 upperWord = kFALSE;
888 }
889 else {
890 // lower word is read first
891 word = (fPayloadCurr[iWord] & 0xffff0000) >> 16;
892 upperWord = kTRUE;
893 continue;
894 }
895
896 if ((word & 0xffff0008) == 0x13370008) {
897 AliDebug(1, Form("stack %i: fast track word: 0x%08x", stack, word));
898 continue;
899 }
900 else if ((word & 0xffff0010) == 0x13370010) {
901 AliDebug(1, Form("stack %i: tracking done word: 0x%08x", stack, word));
902 fCurrTrgFlags[sector] |= 1 << (stack+11);
903 continue;
904 }
905 else if ((idx & 0x1) == 0x1) {
906 trackWord |= ((ULong64_t) word) << 32;
907 AliDebug(1, Form("track debug word: 0x%16llx", trackWord));
908 if (fTracks) {
909 AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
910 AliESDTrdTrack();
911 trk->SetSector(fCurrEquipmentId-kDDLOffset);
912 trk->SetStack((trackWord >> 60) & 0x7);
913 trk->SetA(0);
914 trk->SetB(0);
915 trk->SetPID(0);
916 trk->SetLayerMask((trackWord >> 16) & 0x3f);
917 trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
918 trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
919 trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
920 trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
921 trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
922 trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
923
924 trk->SetFlags(0);
925 trk->SetReserved(0);
926 trk->SetLabel(-3);
927
928 Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
929 if (TMath::Abs(pt) > 0.1) {
930 trk->SetA(-(Int_t) (0.15*51625./100./pt / 160e-4 * 2));
931 }
932 }
933 }
934 else {
935 trackWord = word;
936 }
937 idx++;
938 }
939 }
940 }
941 return 0;
942}
943
944Int_t AliTRDrawStream::ReadTrackingHeader(Int_t stack)
945{
946 // read the tracking information and store it for the given stack
947
948 // index word
949
950 fCurrTrkHeaderIndexWord[stack] = *fPayloadCurr;
951 fCurrTrkHeaderSize[stack] = ((*fPayloadCurr) >> 16) & 0x3ff;
952
953 AliDebug(1, Form("tracking header index word: 0x%08x, size: %i (hw rev: %i)",
954 fCurrTrkHeaderIndexWord[stack], fCurrTrkHeaderSize[stack], fCurrHwRev));
955 Int_t trackingTime = *fPayloadCurr & 0x3ff;
956
957 fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] |= ((fCurrTrkHeaderIndexWord[stack] >> 10) & 0x1) << (22 + stack);
958 fPayloadCurr++;
959
960 // data words
961 ULong64_t trackWord = 0;
962 Int_t idx = 0;
963 Int_t trackIndex = fTracks ? fTracks->GetEntriesFast() : -1;
964
965 for (UInt_t iWord = 0; iWord < fCurrTrkHeaderSize[stack]; iWord++) {
966
967 if (!(idx & 0x1)) {
968 // first part of 64-bit word
969 trackWord = fPayloadCurr[iWord];
970 }
971 else {
972 trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
973
974 if (trackWord & (1ul << 63)) {
975 if ((trackWord & (0x3ful << 56)) != 0) {
976 // track word
977 AliDebug(2, Form("track word: 0x%016llx", trackWord));
978
979 if (fTracks) {
980 AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
981 AliESDTrdTrack();
982
983 trk->SetSector(fCurrEquipmentId-kDDLOffset);
984 trk->SetLayerMask((trackWord >> 56) & 0x3f);
985 trk->SetA( (((trackWord >> 38) & 0x3ffff) ^ 0x20000) - 0x20000);
986 trk->SetB( (((trackWord >> 20) & 0x3ffff) ^ 0x20000) - 0x20000);
987 trk->SetC( (((trackWord >> 8) & 0xffff) ^ 0x8000) - 0x8000);
988 trk->SetPID((trackWord >> 0) & 0xff);
989 trk->SetStack(stack);
990 trk->SetLabel(-3);
991
992 // now compare the track word with the one generated from the ESD information
993 if (trackWord != trk->GetTrackWord(0)) {
994 AliError(Form("track word 0x%016llx does not match the read one 0x%016llx",
995 trk->GetTrackWord(0), trackWord));
996 }
997 }
998 }
999 else {
1000 // done marker (so far only used to set trigger flag)
1001 fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] |= 1 << (27 + stack);
1002 fCurrTrkFlags[(fCurrEquipmentId-kDDLOffset)*fgkNstacks + stack] = trackWord;
1003
1004 AliDebug(2, Form("tracking done marker: 0x%016llx, trigger flags: 0x%08x",
1005 trackWord, fCurrTrgFlags[fCurrEquipmentId-kDDLOffset]));
1006 AliDebug(2, Form("seg / stack / first / last / done / index : %i %i %lli %lli %lli %i",
1007 fCurrEquipmentId - kDDLOffset, stack,
1008 (trackWord >> 20) & 0x3ff,
1009 (trackWord >> 10) & 0x3ff,
1010 (trackWord >> 0) & 0x3ff,
1011 trackingTime));
1012 }
1013 }
1014 else {
1015 // extended track word
1016 AliDebug(2, Form("extended track word: 0x%016llx", trackWord));
1017
1018 if (fTracks) {
1019 AliESDTrdTrack *trk = (AliESDTrdTrack*) (*fTracks)[trackIndex];
1020
1021 trk->SetFlags((trackWord >> 52) & 0x7ff);
1022 trk->SetReserved((trackWord >> 49) & 0x7);
1023 trk->SetY((trackWord >> 36) & 0x1fff);
1024 trk->SetTrackletIndex((trackWord >> 0) & 0x3f, 0);
1025 trk->SetTrackletIndex((trackWord >> 6) & 0x3f, 1);
1026 trk->SetTrackletIndex((trackWord >> 12) & 0x3f, 2);
1027 trk->SetTrackletIndex((trackWord >> 18) & 0x3f, 3);
1028 trk->SetTrackletIndex((trackWord >> 24) & 0x3f, 4);
1029 trk->SetTrackletIndex((trackWord >> 30) & 0x3f, 5);
1030
1031 if (trackWord != trk->GetExtendedTrackWord(0)) {
1032 AliError(Form("extended track word 0x%016llx does not match the read one 0x%016llx",
1033 trk->GetExtendedTrackWord(0), trackWord));
1034 }
1035
1036 trackIndex++;
1037 }
1038 }
1039 }
1040 idx++;
1041 }
1042
1043 fPayloadCurr += fCurrTrkHeaderSize[stack];
1044
1045 return fCurrTrkHeaderSize[stack];
1046}
1047
1048Int_t AliTRDrawStream::ReadTriggerHeaders()
1049{
1050 // read all trigger headers present
1051
1052 AliDebug(1, Form("trigger mask: 0x%03x, fired: 0x%03x\n",
1053 fCurrTriggerEnable, fCurrTriggerFired));
1054 // loop over potential trigger blocks
1055 for (Int_t iTrigger = 0; iTrigger < fgkNtriggers; iTrigger++) {
1056 // check for trigger enable
1057 if (fCurrTriggerEnable & (1 << iTrigger)) {
1058 // check for readout mode and trigger fired
1059 if ((fCurrTrgHeaderReadout == 0) || (fCurrTriggerFired & (1 << iTrigger))) {
1060 // index word
1061 AliDebug(1, Form("trigger index word %i: 0x%08x\n", iTrigger, *fPayloadCurr));
1062 fCurrTrgHeaderIndexWord[iTrigger] = *fPayloadCurr;
1063 fCurrTrgHeaderSize[iTrigger] = ((*fPayloadCurr) >> 16) & 0x3ff;
1064 if (iTrigger == 7) {
1065 // timeout trigger, use to extract tracking time
1066 fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] |= (*fPayloadCurr & 0x3ff) << 12;
1067 }
1068
1069 fPayloadCurr++;
1070 // data words
1071 fPayloadCurr += fCurrTrgHeaderSize[iTrigger];
1072 }
1073 }
1074 }
1075
1076 return 0;
1077}
1078
1079Int_t AliTRDrawStream::ReadStackHeader(Int_t stack)
1080{
1081 // read the stack header
1082 // and store the information in the corresponding variables
1083
1084 fCurrStackIndexWord[stack] = *fPayloadCurr;
1085 fCurrStackHeaderSize[stack] = (((*fPayloadCurr) >> 16) & 0xffff) + 1;
1086 fCurrStackHeaderVersion[stack] = ((*fPayloadCurr) >> 12) & 0xf;
1087 fCurrLinkMask[stack] = (*fPayloadCurr) & 0xfff;
1088
1089 // dumping stack header
1090 AliDebug(1, DumpRaw(Form("stack %i header", stack), fPayloadCurr, fCurrStackHeaderSize[stack]));
1091
1092 if (fPayloadCurr - fPayloadStart >= fPayloadSize - (Int_t) fCurrStackHeaderSize[stack]) {
1093 EquipmentError(kStackHeaderInvalid, "Stack index header %i aborted", stack);
1094 // dumping stack header
1095 AliError(DumpRaw(Form("stack %i header", stack), fPayloadCurr, fCurrStackHeaderSize[stack]));
1096
1097 return -1;
1098 }
1099
1100 switch (fCurrStackHeaderVersion[stack]) {
1101 case 0xa:
1102 if (fCurrStackHeaderSize[stack] < 8) {
1103 LinkError(kStackHeaderInvalid, "Stack header smaller than expected!");
1104 return -1;
1105 }
1106
1107 fCurrCleanCheckout[stack] = fPayloadCurr[1] & 0x1;
1108 fCurrBoardId[stack] = (fPayloadCurr[1] >> 8) & 0xff;
1109 fCurrHwRevTMU[stack] = (fPayloadCurr[1] >> 16) & 0xffff;
1110
1111 for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
1112 // A side
1113 fCurrLinkMonitorFlags [stack*fgkNlinks + iLayer*2] = fPayloadCurr[iLayer+2] & 0xf;
1114 fCurrLinkDataTypeFlags [stack*fgkNlinks + iLayer*2] = (fPayloadCurr[iLayer+2] >> 4) & 0x3;
1115 fCurrLinkDebugFlags [stack*fgkNlinks + iLayer*2] = (fPayloadCurr[iLayer+2] >> 12) & 0xf;
1116 // B side
1117 fCurrLinkMonitorFlags [stack*fgkNlinks + iLayer*2 + 1] = (fPayloadCurr[iLayer+2] >> 16) & 0xf;
1118 fCurrLinkDataTypeFlags [stack*fgkNlinks + iLayer*2 + 1] = (fPayloadCurr[iLayer+2] >> 20) & 0x3;
1119 fCurrLinkDebugFlags [stack*fgkNlinks + iLayer*2 + 1] = (fPayloadCurr[iLayer+2] >> 28) & 0xf;
1120 }
1121 break;
1122
1123 default:
1124 LinkError(kStackHeaderInvalid, "Invalid Stack Header version %x", fCurrStackHeaderVersion[stack]);
1125 }
1126
1127 fPayloadCurr += fCurrStackHeaderSize[stack];
1128
1129 return fCurrStackHeaderSize[stack];
1130}
1131
1132Int_t AliTRDrawStream::ReadGTUTrailer()
1133{
1134 // read the SM trailer containing CRCs from various stages
1135
1136 UInt_t* trailer = fPayloadStart + fPayloadSize -1;
1137
1138 // look for the trailer index word from the end
1139 for (Int_t iWord = 0; iWord < fPayloadSize; iWord++) {
1140 if ((fPayloadStart[fPayloadSize-1-iWord] & 0xffff) == 0x1f51) {
1141 trailer = fPayloadStart + fPayloadSize - 1 - iWord;
1142 break;
1143 }
1144 }
1145
1146 if (((*trailer) & 0xffff) == 0x1f51) {
1147 UInt_t trailerIndexWord = (*trailer);
1148 Int_t trailerSize = (trailerIndexWord >> 16) & 0xffff;
1149 AliDebug(2, DumpRaw("GTU trailer", trailer, trailerSize+1));
1150 // parse the trailer
1151 if (trailerSize >= 4) {
1152 // match flags from GTU
1153 fCurrMatchFlagsSRAM = (trailer[1] >> 0) & 0x1f;
1154 fCurrMatchFlagsPostBP = (trailer[1] >> 5) & 0x1f;
1155 // individual checksums
1156 fCurrChecksumStack[0] = (trailer[1] >> 16) & 0xffff;
1157 fCurrChecksumStack[1] = (trailer[2] >> 0) & 0xffff;
1158 fCurrChecksumStack[2] = (trailer[2] >> 16) & 0xffff;
1159 fCurrChecksumStack[3] = (trailer[3] >> 0) & 0xffff;
1160 fCurrChecksumStack[4] = (trailer[3] >> 16) & 0xffff;
1161 fCurrChecksumSIU = trailer[4];
1162
1163 if ((fCurrMatchFlagsSRAM & fCurrStackMask) != fCurrStackMask)
1164 EquipmentError(kCRCmismatch, "CRC mismatch SRAM: 0x%02x", fCurrMatchFlagsSRAM);
1165 if ((fCurrMatchFlagsPostBP & fCurrStackMask) != fCurrStackMask)
1166 EquipmentError(kCRCmismatch, "CRC mismatch BP: 0x%02x", fCurrMatchFlagsPostBP);
1167
1168 }
1169 else {
1170 LinkError(kUnknown, "Invalid GTU trailer");
1171 }
1172 }
1173 else
1174 EquipmentError(kUnknown, "trailer index marker mismatch");
1175
1176 return 0;
1177}
1178
1179Int_t AliTRDrawStream::ReadLinkData()
1180{
1181 // read the data in one link (one HC) until the data endmarker is reached
1182 // returns the number of words read!
1183
1184 Int_t count = 0;
1185 UInt_t* startPosLink = fPayloadCurr;
1186
1187 AliDebug(1, DumpRaw(Form("link data from seg %2i slot %i link %2i", fCurrEquipmentId-kDDLOffset, fCurrSlot, fCurrLink),
1188 fPayloadCurr, TMath::Min((Int_t) (fPayloadSize - (fPayloadCurr-fPayloadStart)), 100), 0x00000000));
1189
1190 if (fMarkers)
1191 new ((*fMarkers)[fMarkers->GetEntriesFast()])
1192 AliTRDrawStreamError(-kHCactive, fCurrEquipmentId-kDDLOffset, fCurrSlot, fCurrLink);
1193
1194 if (fErrorFlags & kDiscardHC)
1195 return count;
1196
1197 if (fCurrTrackletEnable) {
1198 count += ReadTracklets();
1199 if (fErrorFlags & kDiscardHC)
1200 return count;
1201 }
1202
1203 AliDebug(1, DumpRaw("HC header", fPayloadCurr, 4, 0x00000000));
1204 count += ReadHcHeader();
1205 if (fErrorFlags & kDiscardHC)
1206 return count;
1207
1208 Int_t det = fCurrSm * 30 + fCurrStack * 6 + fCurrLayer;
1209
1210 if (det > -1 && det < 540) {
1211
1212 // ----- check which kind of data -----
1213 if (fCurrMajor & 0x40) {
1214 if ((fCurrMajor & 0x7) == 0x7) {
1215 AliDebug(1, "This is a config event");
1216 UInt_t *startPos = fPayloadCurr;
1217 while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1218 *fPayloadCurr != fgkDataEndmarker)
1219 fPayloadCurr++;
1220 count += fPayloadCurr - startPos;
1221
1222 // feeding TRAP config
1223// AliTRDtrapConfig *trapcfg = AliTRDcalibDB::Instance()->GetTrapConfig();
1224// trapcfg->ReadPackedConfig(fCurrHC, startPos, fPayloadCurr - startPos);
1225 }
1226 else {
1227 Int_t tpmode = fCurrMajor & 0x7;
1228 AliDebug(1, Form("Checking testpattern (mode %i) data", tpmode));
1229 count += ReadTPData(tpmode);
1230 }
1231 }
1232 else {
1233 // reading real data
1234 if (fDigitsManager) {
1235 if ((fAdcArray = fDigitsManager->GetDigits(det))) {
1236 //fAdcArray->Expand();
1237 if (fAdcArray->GetNtime() != fCurrNtimebins)
1238 fAdcArray->Allocate(16, 144, fCurrNtimebins);
1239 }
1240 else {
1241 LinkError(kNoDigits);
1242 }
1243
1244 if (!fDigitsParam) {
1245 fDigitsParam = fDigitsManager->GetDigitsParam();
1246 }
1247 if (fDigitsParam) {
1248 fDigitsParam->SetPretriggerPhase(det, fCurrPtrgPhase);
1249 fDigitsParam->SetNTimeBins(det, fCurrNtimebins);
1250 fDigitsParam->SetADCbaseline(det, 10);
1251 }
1252
1253 if (fDigitsManager->UsesDictionaries()) {
1254 fDigitsManager->GetDictionary(det, 0)->Reset();
1255 fDigitsManager->GetDictionary(det, 1)->Reset();
1256 fDigitsManager->GetDictionary(det, 2)->Reset();
1257 }
1258
1259 if ((fSignalIndex = fDigitsManager->GetIndexes(det))) {
1260 fSignalIndex->SetSM(fCurrSm);
1261 fSignalIndex->SetStack(fCurrStack);
1262 fSignalIndex->SetLayer(fCurrLayer);
1263 fSignalIndex->SetDetNumber(det);
1264 if (!fSignalIndex->IsAllocated())
1265 fSignalIndex->Allocate(16, 144, fCurrNtimebins);
1266 }
1267
1268 if (fCurrMajor & 0x20) {
1269 AliDebug(1, "This is a zs event");
1270 count += ReadZSData();
1271 }
1272 else {
1273 AliDebug(1, "This is a nozs event");
1274 count += ReadNonZSData();
1275 }
1276 }
1277 else {
1278 // just read until data endmarkers
1279 while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1280 *fPayloadCurr != fgkDataEndmarker)
1281 fPayloadCurr++;
1282 }
1283 }
1284 }
1285 else {
1286 LinkError(kInvalidDetector, "%i", det);
1287 while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1288 *fPayloadCurr != fgkDataEndmarker)
1289 fPayloadCurr++;
1290 }
1291
1292 if (fCurrSm > -1 && fCurrSm < 18) {
1293 fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytes += (fPayloadCurr - startPosLink) * sizeof(UInt_t);
1294 fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytesRead += count * sizeof(UInt_t);
1295 fStats.fStatsSector[fCurrSm].fBytesRead += count * sizeof(UInt_t);
1296 fStats.fBytesRead += count * sizeof(UInt_t);
1297 }
1298
1299 return count;
1300}
1301
1302Int_t AliTRDrawStream::ReadTracklets()
1303{
1304 // read the tracklets from one HC
1305
1306 fTrackletArray->Clear();
1307
1308 UInt_t *start = fPayloadCurr;
1309 while (*(fPayloadCurr) != fgkTrackletEndmarker &&
1310 fPayloadCurr - fPayloadStart < fPayloadSize) {
1311 new ((*fTrackletArray)[fTrackletArray->GetEntriesFast()]) AliTRDtrackletWord(*(fPayloadCurr), fCurrHC);
1312
1313 fPayloadCurr++;
1314 }
1315
1316 if (fTrackletArray->GetEntriesFast() > 0) {
1317 AliDebug(1, Form("Found %i tracklets in %i %i %i (ev. %i)", fTrackletArray->GetEntriesFast(),
1318 (fCurrEquipmentId-kDDLOffset), fCurrSlot, fCurrLink, fRawReader->GetEventIndex()));
1319 if (fCurrSm > -1 && fCurrSm < 18) {
1320 fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNTracklets += fTrackletArray->GetEntriesFast();
1321 fStats.fStatsSector[fCurrSm].fNTracklets += fTrackletArray->GetEntriesFast();
1322 }
1323 if (fTrackletTree)
1324 fTrackletTree->Fill();
1325 if (fTracklets)
1326 for (Int_t iTracklet = 0; iTracklet < fTrackletArray->GetEntriesFast(); iTracklet++) {
1327 new ((*fTracklets)[fTracklets->GetEntriesFast()]) AliTRDtrackletWord(*((AliTRDtrackletWord*)(*fTrackletArray)[iTracklet]));
1328 }
1329 }
1330
1331 // loop over remaining tracklet endmarkers
1332 while ((*(fPayloadCurr) == fgkTrackletEndmarker &&
1333 fPayloadCurr - fPayloadStart < fPayloadSize))
1334 fPayloadCurr++;
1335
1336 return fPayloadCurr - start;
1337}
1338
1339Int_t AliTRDrawStream::ReadHcHeader()
1340{
1341 // read and parse the HC header of one HC
1342 // and store the information in the corresponding variables
1343
1344 AliDebug(1, Form("HC header: 0x%08x", *fPayloadCurr));
1345 UInt_t *start = fPayloadCurr;
1346 // check not to be at the data endmarker
1347 if (*fPayloadCurr == fgkDataEndmarker)
1348 return 0;
1349
1350 fCurrSpecial = (*fPayloadCurr >> 31) & 0x1;
1351 fCurrMajor = (*fPayloadCurr >> 24) & 0x7f;
1352 fCurrMinor = (*fPayloadCurr >> 17) & 0x7f;
1353 fCurrAddHcWords = (*fPayloadCurr >> 14) & 0x7;
1354 fCurrSm = (*fPayloadCurr >> 9) & 0x1f;
1355 fCurrLayer = (*fPayloadCurr >> 6) & 0x7;
1356 fCurrStack = (*fPayloadCurr >> 3) & 0x7;
1357 fCurrSide = (*fPayloadCurr >> 2) & 0x1;
1358 fCurrCheck = (*fPayloadCurr) & 0x3;
1359
1360 if ((fCurrSm != (((Int_t) fCurrEquipmentId) - kDDLOffset)) ||
1361 (fCurrStack != fCurrSlot) ||
1362 (fCurrLayer != fCurrLink / 2) ||
1363 (fCurrSide != fCurrLink % 2)) {
1364 LinkError(kHCmismatch,
1365 "HC: %i, %i, %i, %i\n 0x%08x 0x%08x 0x%08x 0x%08x",
1366 fCurrSm, fCurrStack, fCurrLayer, fCurrSide,
1367 fPayloadCurr[0], fPayloadCurr[1], fPayloadCurr[2], fPayloadCurr[3]);
1368 }
1369 if (fCurrCheck != 0x1) {
1370 LinkError(kHCcheckFailed);
1371 }
1372
1373 if (fCurrAddHcWords > 0) {
1374 fCurrNtimebins = (fPayloadCurr[1] >> 26) & 0x3f;
1375 fCurrBC = (fPayloadCurr[1] >> 10) & 0xffff;
1376 fCurrPtrgCnt = (fPayloadCurr[1] >> 6) & 0xf;
1377 fCurrPtrgPhase = (fPayloadCurr[1] >> 2) & 0xf;
1378 }
1379
1380 fPayloadCurr += 1 + fCurrAddHcWords;
1381
1382 return (fPayloadCurr - start);
1383}
1384
1385Int_t AliTRDrawStream::ReadTPData(Int_t mode)
1386{
1387 // testing of testpattern 1 to 3 (hardcoded), 0 missing
1388 // evcnt checking missing
1389 Int_t cpu = 0;
1390 Int_t cpufromchannel[] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3};
1391 Int_t evno = -1;
1392 Int_t evcnt = 0;
1393 Int_t count = 0;
1394 Int_t mcmcount = -1;
1395 Int_t wordcount = 0;
1396 Int_t channelcount = 0;
1397 UInt_t expword = 0;
1398 UInt_t expadcval = 0;
1399 UInt_t diff = 0;
1400 Int_t lastmcmpos = -1;
1401 Int_t lastrobpos = -1;
1402
1403 UInt_t* start = fPayloadCurr;
1404
1405 while (*(fPayloadCurr) != fgkDataEndmarker &&
1406 fPayloadCurr - fPayloadStart < fPayloadSize - 1) {
1407
1408 // ----- Checking MCM Header -----
1409 AliDebug(2, DumpMcmHeader("MCM header: ", *fPayloadCurr));
1410 UInt_t *startPosMCM = fPayloadCurr;
1411 mcmcount++;
1412
1413 // ----- checking for proper readout order - ROB -----
1414 fCurrRobPos = ROB(*fPayloadCurr);
1415 if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1416 if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
1417 lastmcmpos = -1;
1418 lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1419 }
1420 else {
1421 ROBError(kPosUnexp, Form("#%i after #%i in readout order", GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos));
1422 }
1423
1424 // ----- checking for proper readout order - MCM -----
1425 fCurrMcmPos = MCM(*fPayloadCurr);
1426 if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
1427 lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
1428 }
1429 else {
1430 MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
1431 }
1432
1433 if (EvNo(*fPayloadCurr) != evno) {
1434 if (evno == -1) {
1435 evno = EvNo(*fPayloadCurr);
1436 }
1437 else {
1438 MCMError(kEvCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
1439 }
1440 }
1441
1442 fPayloadCurr++;
1443
1444 evcnt = 0x3f & *fPayloadCurr >> 26;
1445 cpu = -1;
1446 channelcount = 0;
1447 while (channelcount < 21) {
1448 count = 0;
1449 if (cpu != cpufromchannel[channelcount]) {
1450 cpu = cpufromchannel[channelcount];
1451 expadcval = (1 << 9) | (fCurrRobPos << 6) | (fCurrMcmPos << 2) | cpu;
1452 wordcount = 0;
1453 }
1454
1455 while (count < 10) {
1456 if (*fPayloadCurr == fgkDataEndmarker) {
1457 MCMError(kMissTpData);
1458 return (fPayloadCurr - start);
1459 }
1460
1461 if (channelcount % 2 == 0)
1462 expword = 0x3;
1463 else
1464 expword = 0x2;
1465
1466 if (mode == 1) {
1467 // ----- TP 1 -----
1468 expword |= expadcval << 2;
1469 expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
1470 expword |= expadcval << 12;
1471 expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
1472 expword |= expadcval << 22;
1473 expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
1474 }
1475 else if (mode == 2) {
1476 // ----- TP 2 ------
1477 expword = ((0x3f & evcnt) << 26) | ((fCurrSm + 1) << 21) | ((fCurrLayer + 1) << 18) |
1478 ((fCurrStack + 1) << 15) |
1479 (fCurrRobPos << 12) | (fCurrMcmPos << 8) | (cpu << 6) | (wordcount + 1);
1480 }
1481 else if (mode == 3) {
1482 // ----- TP 3 -----
1483 expword = ((0xfff & evcnt) << 20) | (fCurrSm << 15) | (fCurrLink/2 << 12) | (fCurrStack << 9) |
1484 (fCurrRobPos << 6) | (fCurrMcmPos << 2) | (cpu << 0);
1485 }
1486 else {
1487 expword = 0;
1488 LinkError(kTPmodeInvalid, "Just reading");
1489 }
1490
1491 diff = *fPayloadCurr ^ expword;
1492 AliDebug(11, Form("Comparing ch %2i, word %2i (cpu %i): 0x%08x <-> 0x%08x",
1493 channelcount, wordcount, cpu, *fPayloadCurr, expword));
1494
1495 if (diff != 0) {
1496 MCMError(kTPmismatch,
1497 "Seen 0x%08x, expected 0x%08x, diff: 0x%08x, 0x%04x, 0x%02x - word %2i (cpu %i, ch %i)",
1498 *fPayloadCurr, expword, diff,
1499 0xffff & (diff | diff >> 16),
1500 0xff & (diff | diff >> 8 | diff >> 16 | diff >> 24),
1501 wordcount, cpu, channelcount);;
1502 }
1503 fPayloadCurr++;
1504 count++;
1505 wordcount++;
1506 if (*fPayloadCurr == fgkDataEndmarker)
1507 return (fPayloadCurr - start);
1508 }
1509 channelcount++;
1510 }
1511 // continue with next MCM
1512
1513 if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
1514 AliInfo(DumpRaw(Form("Event %i: Det %3i ROB %i MCM %2i", fRawReader->GetEventIndex(), fCurrHC/2, fCurrRobPos, fCurrMcmPos),
1515 startPosMCM, fPayloadCurr - startPosMCM));
1516 }
1517
1518 }
1519 return fPayloadCurr - start;
1520}
1521
1522
1523Int_t AliTRDrawStream::ReadZSData()
1524{
1525 // read the zs data from one link from the current reading position
1526
1527 UInt_t *start = fPayloadCurr;
1528
1529 Int_t mcmcount = 0;
1530 Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
1531 Int_t channelcount = 0;
1532 Int_t channelcountExp = 0;
1533 Int_t channelcountMax = 0;
1534 Int_t timebins;
1535 Int_t currentTimebin = 0;
1536 Int_t adcwc = 0;
1537 Int_t evno = -1;
1538 Int_t lastmcmpos = -1;
1539 Int_t lastrobpos = -1;
1540
1541 if (fCurrNtimebins != fNtimebins) {
1542 if (fNtimebins > 0)
1543 LinkError(kNtimebinsChanged,
1544 "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
1545 fNtimebins = fCurrNtimebins;
1546 }
1547
1548 timebins = fNtimebins;
1549
1550 while (*(fPayloadCurr) != fgkDataEndmarker &&
1551 fPayloadCurr - fPayloadStart < fPayloadSize) {
1552
1553 // ----- Checking MCM Header -----
1554 AliDebug(2, DumpMcmHeader("MCM header: ", *fPayloadCurr));
1555 UInt_t *startPosMCM = fPayloadCurr;
1556
1557 // ----- checking for proper readout order - ROB -----
1558 fCurrRobPos = ROB(*fPayloadCurr);
1559 if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1560 if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
1561 lastmcmpos = -1;
1562 lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1563 }
1564 else {
1565 ROBError(kPosUnexp, Form("#%i after #%i and #%i in readout order",
1566 GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos, GetROBReadoutPos(fCurrRobPos)));
1567 }
1568
1569 // ----- checking for proper readout order - MCM -----
1570 fCurrMcmPos = MCM(*fPayloadCurr);
1571 if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
1572 lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
1573 }
1574 else {
1575 MCMError(kPosUnexp, Form("#%i after #%i and #%i in readout order",
1576 GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos, GetMCMReadoutPos(fCurrMcmPos)));
1577 }
1578
1579 if (EvNo(*fPayloadCurr) != evno) {
1580 if (evno == -1)
1581 evno = EvNo(*fPayloadCurr);
1582 else {
1583 MCMError(kEvCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
1584 }
1585 }
1586 Int_t adccoloff = AdcColOffset(*fPayloadCurr);
1587 Int_t padcoloff = PadColOffset(*fPayloadCurr);
1588 Int_t row = Row(*fPayloadCurr);
1589 fPayloadCurr++;
1590
1591 if ((row > 11) && (fCurrStack == 2)) {
1592 MCMError(kUnknown, "Data in padrow > 11 for stack 2");
1593 }
1594
1595 // ----- Reading ADC channels -----
1596 AliDebug(2, DumpAdcMask("ADC mask: ", *fPayloadCurr));
1597
1598 // ----- analysing the ADC mask -----
1599 channelcount = 0;
1600 channelcountExp = GetNActiveChannelsFromMask(*fPayloadCurr);
1601 channelcountMax = GetNActiveChannels(*fPayloadCurr);
1602 Int_t channelmask = GetActiveChannels(*fPayloadCurr);
1603 Int_t channelno = -1;
1604 fPayloadCurr++;
1605
1606 if (channelcountExp != channelcountMax) {
1607 if (channelcountExp > channelcountMax) {
1608 Int_t temp = channelcountExp;
1609 channelcountExp = channelcountMax;
1610 channelcountMax = temp;
1611 }
1612 while (channelcountExp < channelcountMax && channelcountExp < 21 &&
1613 fPayloadCurr - fPayloadStart < fPayloadSize - 10 * channelcountExp - 1) {
1614 MCMError(kAdcMaskInconsistent,
1615 "Possible MCM-H: 0x%08x, possible ADC-mask: 0x%08x",
1616 *(fPayloadCurr + 10 * channelcountExp),
1617 *(fPayloadCurr + 10 * channelcountExp + 1) );
1618 if (!CouldBeMCMhdr( *(fPayloadCurr + 10 * channelcountExp)) && !CouldBeADCmask( *(fPayloadCurr + 10 * channelcountExp + 1)))
1619 channelcountExp++;
1620 else {
1621 break;
1622 }
1623 }
1624 MCMError(kAdcMaskInconsistent,
1625 "Inconsistency in no. of active channels: Counter: %i, Mask: %i, chosen: %i!",
1626 GetNActiveChannels(fPayloadCurr[-1]), GetNActiveChannelsFromMask(fPayloadCurr[-1]), channelcountExp);
1627 }
1628 AliDebug(2, Form("expecting %i active channels, %i timebins", channelcountExp, fCurrNtimebins));
1629
1630 // ----- reading marked ADC channels -----
1631 while (channelcount < channelcountExp && *(fPayloadCurr) != fgkDataEndmarker) {
1632 if (channelno < 20)
1633 channelno++;
1634 while (channelno < 20 && (channelmask & 1 << channelno) == 0)
1635 channelno++;
1636
1637 if (fCurrNtimebins > 30) {
1638 currentTimebin = ((*fPayloadCurr >> 2) & 0x3f);
1639 timebins = ((*fPayloadCurr >> 8) & 0xf) * 3;
1640 }
1641 else {
1642 currentTimebin = 0;
1643 }
1644
1645 adcwc = 0;
1646 Int_t nADCwords = (timebins + 2) / 3;
1647 AliDebug(3, Form("Now reading %i words for channel %2i", nADCwords, channelno));
1648 Int_t adccol = adccoloff - channelno;
1649 Int_t padcol = padcoloff - channelno;
1650// if (adccol < 3 || adccol > 165)
1651// AliInfo(Form("writing channel %i of det %3i %i:%2i to adcrow/-col: %i/%i padcol: %i",
1652// channelno, fCurrHC/2, fCurrRobPos, fCurrMcmPos, row, adccol, padcol));
1653
1654 while ((adcwc < nADCwords) &&
1655 (*(fPayloadCurr) != fgkDataEndmarker) &&
1656 (fPayloadCurr - fPayloadStart < fPayloadSize)) {
1657 int check = 0x3 & *fPayloadCurr;
1658 if (channelno % 2 != 0) { // odd channel
1659 if (check != 0x2 && channelno < 21) {
1660 MCMError(kAdcCheckInvalid,
1661 "%i for %2i. ADC word in odd channel %i",
1662 check, adcwc+1, channelno);
1663 }
1664 }
1665 else { // even channel
1666 if (check != 0x3 && channelno < 21) {
1667 MCMError(kAdcCheckInvalid,
1668 "%i for %2i. ADC word in even channel %i",
1669 check, adcwc+1, channelno);
1670 }
1671 }
1672
1673 // filling the actual timebin data
1674 int tb2 = 0x3ff & *fPayloadCurr >> 22;
1675 int tb1 = 0x3ff & *fPayloadCurr >> 12;
1676 int tb0 = 0x3ff & *fPayloadCurr >> 2;
1677 if (adcwc != 0 || fCurrNtimebins <= 30)
1678 fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
1679 else
1680 tb0 = -1;
1681 fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
1682 fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
1683
1684 adcwc++;
1685 fPayloadCurr++;
1686 }
1687
1688 if (adcwc != nADCwords)
1689 MCMError(kAdcDataAbort);
1690
1691 // adding index
1692 if (padcol > 0 && padcol < 144) {
1693 fSignalIndex->AddIndexRC(row, padcol);
1694 }
1695
1696 channelcount++;
1697 }
1698
1699 if (fCurrSm > -1 && fCurrSm < 18) {
1700 fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNChannels += channelcount;
1701 fStats.fStatsSector[fCurrSm].fNChannels += channelcount;
1702 }
1703 if (channelcount != channelcountExp)
1704 MCMError(kAdcChannelsMiss);
1705
1706 mcmcount++;
1707 if (fCurrSm > -1 && fCurrSm < 18) {
1708 fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNMCMs++;
1709 fStats.fStatsSector[fCurrSm].fNMCMs++;
1710 }
1711
1712 if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
1713 AliInfo(DumpRaw(Form("Event %i: Det %3i ROB %i MCM %2i", fRawReader->GetEventIndex(), fCurrHC/2, fCurrRobPos, fCurrMcmPos),
1714 startPosMCM, fPayloadCurr - startPosMCM));
1715 }
1716
1717 // continue with next MCM
1718 }
1719
1720 // check for missing MCMs (if header suppression is inactive)
1721 if (((fCurrMajor & 0x1) == 0) && (mcmcount != mcmcountExp)) {
1722 LinkError(kMissMcmHeaders,
1723 "No. of MCM headers %i not as expected: %i",
1724 mcmcount, mcmcountExp);
1725 }
1726
1727 return (fPayloadCurr - start);
1728}
1729
1730Int_t AliTRDrawStream::ReadNonZSData()
1731{
1732 // read the non-zs data from one link from the current reading position
1733
1734 UInt_t *start = fPayloadCurr;
1735
1736 Int_t mcmcount = 0;
1737 Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
1738 Int_t channelcount = 0;
1739 Int_t channelcountExp = 0;
1740 Int_t timebins;
1741 Int_t currentTimebin = 0;
1742 Int_t adcwc = 0;
1743 Int_t evno = -1;
1744 Int_t lastmcmpos = -1;
1745 Int_t lastrobpos = -1;
1746
1747 if (fCurrNtimebins != fNtimebins) {
1748 if (fNtimebins > 0)
1749 LinkError(kNtimebinsChanged,
1750 "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
1751 fNtimebins = fCurrNtimebins;
1752 }
1753
1754 timebins = fNtimebins;
1755
1756 while (*(fPayloadCurr) != fgkDataEndmarker &&
1757 fPayloadCurr - fPayloadStart < fPayloadSize - 2) {
1758
1759 // ----- Checking MCM Header -----
1760 AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
1761
1762 // ----- checking for proper readout order - ROB -----
1763 fCurrRobPos = ROB(*fPayloadCurr);
1764 if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1765 if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
1766 lastmcmpos = -1;
1767 lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1768 }
1769 else {
1770 ROBError(kPosUnexp, Form("#%i after #%i in readout order", GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos));
1771 }
1772
1773 // ----- checking for proper readout order - MCM -----
1774 fCurrMcmPos = MCM(*fPayloadCurr);
1775 if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
1776 lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
1777 }
1778 else {
1779 MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
1780 }
1781
1782 if (EvNo(*fPayloadCurr) != evno) {
1783 if (evno == -1)
1784 evno = EvNo(*fPayloadCurr);
1785 else {
1786 MCMError(kEvCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
1787 }
1788 }
1789
1790 channelcount = 0;
1791 channelcountExp = 21;
1792 int channelno = -1;
1793
1794 Int_t adccoloff = AdcColOffset(*fPayloadCurr);
1795 Int_t padcoloff = PadColOffset(*fPayloadCurr);
1796 Int_t row = Row(*fPayloadCurr);
1797
1798 fPayloadCurr++;
1799
1800 // ----- reading marked ADC channels -----
1801 while (channelcount < channelcountExp &&
1802 *(fPayloadCurr) != fgkDataEndmarker) {
1803 if (channelno < 20)
1804 channelno++;
1805
1806 currentTimebin = 0;
1807
1808 adcwc = 0;
1809 Int_t nADCwords = (timebins + 2) / 3;
1810 AliDebug(2, Form("Now looking %i words", nADCwords));
1811 Int_t adccol = adccoloff - channelno;
1812 Int_t padcol = padcoloff - channelno;
1813 while ((adcwc < nADCwords) &&
1814 (*(fPayloadCurr) != fgkDataEndmarker) &&
1815 (fPayloadCurr - fPayloadStart < fPayloadSize)) {
1816 int check = 0x3 & *fPayloadCurr;
1817 if (channelno % 2 != 0) { // odd channel
1818 if (check != 0x2 && channelno < 21) {
1819 MCMError(kAdcCheckInvalid,
1820 "%i for %2i. ADC word in odd channel %i",
1821 check, adcwc+1, channelno);
1822 }
1823 }
1824 else { // even channel
1825 if (check != 0x3 && channelno < 21) {
1826 MCMError(kAdcCheckInvalid,
1827 "%i for %2i. ADC word in even channel %i",
1828 check, adcwc+1, channelno);
1829 }
1830 }
1831
1832 // filling the actual timebin data
1833 int tb2 = 0x3ff & *fPayloadCurr >> 22;
1834 int tb1 = 0x3ff & *fPayloadCurr >> 12;
1835 int tb0 = 0x3ff & *fPayloadCurr >> 2;
1836 if (adcwc != 0 || fCurrNtimebins <= 30)
1837 fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
1838 else
1839 tb0 = -1;
1840 fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
1841 fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
1842
1843 adcwc++;
1844 fPayloadCurr++;
1845 }
1846
1847 if (adcwc != nADCwords)
1848 MCMError(kAdcDataAbort);
1849
1850 // adding index
1851 if (padcol > 0 && padcol < 144) {
1852 fSignalIndex->AddIndexRC(row, padcol);
1853 }
1854
1855 channelcount++;
1856 }
1857
1858 if (channelcount != channelcountExp)
1859 MCMError(kAdcChannelsMiss);
1860 mcmcount++;
1861 // continue with next MCM
1862 }
1863
1864 // check for missing MCMs (if header suppression is inactive)
1865 if (mcmcount != mcmcountExp) {
1866 LinkError(kMissMcmHeaders,
1867 "%i not as expected: %i", mcmcount, mcmcountExp);
1868 }
1869
1870 return (fPayloadCurr - start);
1871}
1872
1873Int_t AliTRDrawStream::SeekNextStack()
1874{
1875 // proceed in raw data stream till the next stack
1876
1877 if (!fCurrStackEndmarkerAvail)
1878 return 0;
1879
1880 UInt_t *start = fPayloadCurr;
1881
1882 // read until data endmarkers
1883 while ((fPayloadCurr - fPayloadStart < fPayloadSize-1) &&
1884 ((fPayloadCurr[0] != fgkStackEndmarker[0]) ||
1885 (fPayloadCurr[1] != fgkStackEndmarker[1])))
1886 fPayloadCurr++;
1887
1888 if ((fPayloadCurr - start) != 0)
1889 StackError(kUnknown, "skipped %i words to reach stack endmarker", fPayloadCurr - start);
1890
1891 AliDebug(2, Form("stack endmarker: 0x%08x 0x%08x", fPayloadCurr[0], fPayloadCurr[1]));
1892
1893 // goto next stack
1894 fPayloadCurr++;
1895 fPayloadCurr++;
1896
1897 return (fPayloadCurr-start);
1898}
1899
1900Int_t AliTRDrawStream::SeekNextLink()
1901{
1902 // proceed in raw data stream till the next link
1903
1904 UInt_t *start = fPayloadCurr;
1905
1906 // read until data endmarkers
1907 while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1908 *fPayloadCurr != fgkDataEndmarker)
1909 fPayloadCurr++;
1910
1911 // read all data endmarkers
1912 while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1913 *fPayloadCurr == fgkDataEndmarker)
1914 fPayloadCurr++;
1915
1916 return (fPayloadCurr - start);
1917}
1918
1919Bool_t AliTRDrawStream::ConnectTracklets(TTree *trklTree)
1920{
1921 // connect the tracklet tree used to store the tracklet output
1922
1923 fTrackletTree = trklTree;
1924 if (!fTrackletTree)
1925 return kTRUE;
1926
1927 if (!fTrackletTree->GetBranch("hc"))
1928 fTrackletTree->Branch("hc", &fCurrHC, "hc/I");
1929 else
1930 fTrackletTree->SetBranchAddress("hc", &fCurrHC);
1931
1932 if (!fTrackletTree->GetBranch("trkl"))
1933 fTrackletTree->Branch("trkl", &fTrackletArray);
1934 else
1935 fTrackletTree->SetBranchAddress("trkl", &fTrackletArray);
1936
1937 return kTRUE;
1938}
1939
1940
1941void AliTRDrawStream::EquipmentError(ErrorCode_t err, const char *const msg, ...)
1942{
1943 // register error according to error code on equipment level
1944 // and return the corresponding error message
1945
1946 fLastError.fSector = fCurrEquipmentId - kDDLOffset;
1947 fLastError.fStack = -1;
1948 fLastError.fLink = -1;
1949 fLastError.fRob = -1;
1950 fLastError.fMcm = -1;
1951 fLastError.fError = err;
1952 (this->*fStoreError)();
1953
1954 va_list ap;
1955 if (fgErrorDebugLevel[err] > 10)
1956 AliDebug(fgErrorDebugLevel[err],
1957 Form("Event %6i: Eq. %2d - %s : %s",
1958 fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
1959 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1960 else
1961 AliError(Form("Event %6i: Eq. %2d - %s : %s",
1962 fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
1963 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1964 fErrorFlags |= fgErrorBehav[err];
1965}
1966
1967
1968void AliTRDrawStream::StackError(ErrorCode_t err, const char *const msg, ...)
1969{
1970 // register error according to error code on stack level
1971 // and return the corresponding error message
1972
1973 fLastError.fSector = fCurrEquipmentId - kDDLOffset;
1974 fLastError.fStack = fCurrSlot;
1975 fLastError.fLink = -1;
1976 fLastError.fRob = -1;
1977 fLastError.fMcm = -1;
1978 fLastError.fError = err;
1979 (this->*fStoreError)();
1980
1981 va_list ap;
1982 if (fgErrorDebugLevel[err] > 0)
1983 AliDebug(fgErrorDebugLevel[err],
1984 Form("Event %6i: Eq. %2d S %i - %s : %s",
1985 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
1986 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1987 else
1988 AliError(Form("Event %6i: Eq. %2d S %i - %s : %s",
1989 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
1990 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1991 fErrorFlags |= fgErrorBehav[err];
1992}
1993
1994
1995void AliTRDrawStream::LinkError(ErrorCode_t err, const char *const msg, ...)
1996{
1997 // register error according to error code on link level
1998 // and return the corresponding error message
1999
2000 fLastError.fSector = fCurrEquipmentId - kDDLOffset;
2001 fLastError.fStack = fCurrSlot;
2002 fLastError.fLink = fCurrLink;
2003 fLastError.fRob = -1;
2004 fLastError.fMcm = -1;
2005 fLastError.fError = err;
2006 (this->*fStoreError)();
2007
2008 va_list ap;
2009 if (fgErrorDebugLevel[err] > 0)
2010 AliDebug(fgErrorDebugLevel[err],
2011 Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
2012 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
2013 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2014 else
2015 AliError(Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
2016 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
2017 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2018 fErrorFlags |= fgErrorBehav[err];
2019}
2020
2021
2022void AliTRDrawStream::ROBError(ErrorCode_t err, const char *const msg, ...)
2023{
2024 // register error according to error code on ROB level
2025 // and return the corresponding error message
2026
2027 fLastError.fSector = fCurrEquipmentId - kDDLOffset;
2028 fLastError.fStack = fCurrSlot;
2029 fLastError.fLink = fCurrLink;
2030 fLastError.fRob = fCurrRobPos;
2031 fLastError.fMcm = -1;
2032 fLastError.fError = err;
2033 (this->*fStoreError)();
2034
2035 va_list ap;
2036 if (fgErrorDebugLevel[err] > 0)
2037 AliDebug(fgErrorDebugLevel[err],
2038 Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
2039 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
2040 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2041 else
2042 AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
2043 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
2044 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2045 fErrorFlags |= fgErrorBehav[err];
2046}
2047
2048
2049void AliTRDrawStream::MCMError(ErrorCode_t err, const char *const msg, ...)
2050{
2051 // register error according to error code on MCM level
2052 // and return the corresponding error message
2053
2054 fLastError.fSector = fCurrEquipmentId - kDDLOffset;
2055 fLastError.fStack = fCurrSlot;
2056 fLastError.fLink = fCurrLink;
2057 fLastError.fRob = fCurrRobPos;
2058 fLastError.fMcm = fCurrMcmPos;
2059 fLastError.fError = err;
2060 (this->*fStoreError)();
2061
2062 va_list ap;
2063 if (fgErrorDebugLevel[err] > 0)
2064 AliDebug(fgErrorDebugLevel[err],
2065 Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
2066 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
2067 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2068 else
2069 AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
2070 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
2071 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2072 fErrorFlags |= fgErrorBehav[err];
2073}
2074
2075const char* AliTRDrawStream::GetErrorMessage(ErrorCode_t errCode)
2076{
2077 // return the error message for the given error code
2078
2079 if (errCode > 0 && errCode < kLastErrorCode)
2080 return fgkErrorMessages[errCode];
2081 else
2082 return "";
2083}
2084
2085void AliTRDrawStream::AliTRDrawStats::ClearStats()
2086{
2087 // clear statistics (includes clearing sector-wise statistics)
2088
2089 fBytesRead = 0;
2090 for (Int_t iSector = 0; iSector < 18; iSector++) {
2091 fStatsSector[iSector].ClearStats();
2092 }
2093
2094}
2095
2096void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::ClearStats()
2097{
2098 // clear statistics (includes clearing HC-wise statistics)
2099
2100 fBytes = 0;
2101 fBytesRead = 0;
2102 fNTracklets = 0;
2103 fNMCMs = 0;
2104 fNChannels = 0;
2105
2106 for (Int_t iHC = 0; iHC < 60; iHC++) {
2107 fStatsHC[iHC].ClearStats();
2108 }
2109}
2110
2111void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::AliTRDrawStatsHC::ClearStats()
2112{
2113 // clear statistics
2114
2115 fBytes = 0;
2116 fBytesRead = 0;
2117 fNTracklets = 0;
2118 fNMCMs = 0;
2119 fNChannels = 0;
2120}
2121
2122void AliTRDrawStream::SetDumpMCM(Int_t det, Int_t rob, Int_t mcm, Bool_t dump)
2123{
2124 // mark MCM for dumping of raw data
2125
2126 if (dump) {
2127 fDumpMCM[fNDumpMCMs++] = (det << 7) | (rob << 4) | mcm;
2128 }
2129 else {
2130 Int_t iMCM;
2131 for (iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
2132 if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
2133 fNDumpMCMs--;
2134 break;
2135 }
2136 }
2137 for ( ; iMCM < fNDumpMCMs; iMCM++) {
2138 fDumpMCM[iMCM] = fDumpMCM[iMCM+1];
2139 }
2140 }
2141}
2142
2143Bool_t AliTRDrawStream::DumpingMCM(Int_t det, Int_t rob, Int_t mcm) const
2144{
2145 // check if MCM data should be dumped
2146
2147 for (Int_t iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
2148 if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
2149 return kTRUE;
2150 }
2151 }
2152 return kFALSE;
2153}
2154
2155TString AliTRDrawStream::DumpRaw(TString title, UInt_t *start, Int_t length, UInt_t endmarker)
2156{
2157 // dump raw data
2158
2159 title += "\n";
2160 for (Int_t pos = 0; pos < length; pos += 4) {
2161 if ((start[pos+0] != endmarker) && pos+0 < length)
2162 if ((start[pos+1] != endmarker && pos+1 < length))
2163 if ((start[pos+2] != endmarker && pos+2 < length))
2164 if ((start[pos+3] != endmarker && pos+3 < length))
2165 title += Form(" 0x%08x 0x%08x 0x%08x 0x%08x\n",
2166 start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
2167 else {
2168 title += Form(" 0x%08x 0x%08x 0x%08x 0x%08x\n",
2169 start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
2170 return title;
2171 }
2172 else {
2173 title += Form(" 0x%08x 0x%08x 0x%08x\n",
2174 start[pos+0], start[pos+1], start[pos+2]);
2175 return title;
2176 }
2177 else {
2178 title += Form(" 0x%08x 0x%08x\n",
2179 start[pos+0], start[pos+1]);
2180 return title;
2181 }
2182 else {
2183 title += Form(" 0x%08x\n",
2184 start[pos+0]);
2185 return title;
2186 }
2187 }
2188 return title;
2189}
2190
2191TString AliTRDrawStream::DumpMcmHeader(TString title, UInt_t word)
2192{
2193 title += Form("0x%08x -> ROB: %i, MCM: %2i",
2194 word, ROB(word), MCM(word));
2195 return title;
2196}
2197
2198TString AliTRDrawStream::DumpAdcMask(TString title, UInt_t word)
2199{
2200 title += Form("0x%08x -> #ch : %2i, 0x%06x (%2i ch)",
2201 word, GetNActiveChannels(word), GetActiveChannels(word), GetNActiveChannelsFromMask(word));
2202 return title;
2203}
2204
2205AliTRDrawStream::AliTRDrawStreamError::AliTRDrawStreamError(Int_t error, Int_t sector, Int_t stack, Int_t link, Int_t rob, Int_t mcm) :
2206 fError(error),
2207 fSector(sector),
2208 fStack(stack),
2209 fLink(link),
2210 fRob(rob),
2211 fMcm(mcm)
2212{
2213 // ctor
2214
2215}
2216
2217void AliTRDrawStream::SortTracklets(TClonesArray *trklArray, TList &sortedTracklets, Int_t *indices)
2218{
2219 // sort tracklets for referencing from GTU tracks
2220
2221 Int_t nTracklets = trklArray->GetEntriesFast();
2222
2223 Int_t lastHC = -1;
2224 for (Int_t iTracklet = 0; iTracklet < nTracklets; iTracklet++) {
2225 AliTRDtrackletBase *trkl = (AliTRDtrackletBase*) ((*trklArray)[iTracklet]);
2226 Int_t hc = trkl->GetHCId();
2227 if ((hc < 0) || (hc >= 1080)) {
2228 AliErrorClass(Form("HC for tracklet: 0x%08x out of range: %i", trkl->GetTrackletWord(), trkl->GetHCId()));
2229 continue;
2230 }
2231 AliDebugClass(5, Form("hc: %4i : 0x%08x z: %2i", hc, trkl->GetTrackletWord(), trkl->GetZbin()));
2232 if (hc != lastHC) {
2233 AliDebugClass(2, Form("set tracklet index for HC %i to %i", hc, iTracklet));
2234 indices[hc] = iTracklet + 1;
2235 lastHC = hc;
2236 }
2237 }
2238
2239 for (Int_t iDet = 0; iDet < 540; iDet++) {
2240 Int_t trklIndexA = indices[2*iDet + 0] - 1;
2241 Int_t trklIndexB = indices[2*iDet + 1] - 1;
2242 Int_t trklIndex = sortedTracklets.GetEntries();
2243 AliTRDtrackletBase *trklA = trklIndexA > -1 ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
2244 AliTRDtrackletBase *trklB = trklIndexB > -1 ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
2245 AliTRDtrackletBase *trklNext = 0x0;
2246 while (trklA != 0x0 || trklB != 0x0) {
2247 AliDebugClass(5, Form("det %i - A: %i/%i -> %p, B: %i/%i -> %p",
2248 iDet, trklIndexA, nTracklets, trklA, trklIndexB, nTracklets, trklB));
2249 if (trklA == 0x0) {
2250 trklNext = trklB;
2251 trklIndexB++;
2252 trklB = trklIndexB < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
2253 if (trklB && trklB->GetHCId() != 2*iDet + 1)
2254 trklB = 0x0;
2255 }
2256 else if (trklB == 0x0) {
2257 trklNext = trklA;
2258 trklIndexA++;
2259 trklA = trklIndexA < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
2260 if (trklA && trklA->GetHCId() != 2*iDet)
2261 trklA = 0x0;
2262 }
2263 else {
2264 if ((trklA->GetZbin() < trklB->GetZbin()) ||
2265 ((trklA->GetZbin() == trklB->GetZbin()) && (trklA->GetYbin() < trklB->GetYbin()))) {
2266 trklNext = trklA;
2267 trklIndexA++;
2268 trklA = trklIndexA < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
2269 if (trklA && trklA->GetHCId() != 2*iDet)
2270 trklA = 0x0;
2271 }
2272 else {
2273 trklNext = trklB;
2274 trklIndexB++;
2275 trklB = trklIndexB < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
2276 if (trklB && trklB->GetHCId() != 2*iDet + 1)
2277 trklB = 0x0;
2278 }
2279 }
2280 if (trklNext) {
2281 Int_t label = -2; // mark raw tracklets with label -2
2282 if (AliTRDtrackletMCM *trklMCM = dynamic_cast<AliTRDtrackletMCM*> (trklNext))
2283 label = trklMCM->GetLabel();
2284 AliESDTrdTracklet *esdTracklet = new AliESDTrdTracklet(trklNext->GetTrackletWord(), trklNext->GetHCId(), label);
2285 sortedTracklets.Add(esdTracklet);
2286 }
2287
2288 // updating tracklet indices as in output
2289 if (sortedTracklets.GetEntries() != trklIndex) {
2290 indices[2*iDet + 0] = indices[2*iDet + 1] = trklIndex;
2291 }
2292 else
2293 indices[2*iDet + 0] = indices[2*iDet + 1] = -1;
2294 }
2295 }
2296}