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