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