- support for no. of timebins != 3*n
[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         if (currentTimebin >= fCurrNtimebins)
1703           break;
1704         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
1705         if (currentTimebin >= fCurrNtimebins)
1706           break;
1707         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
1708
1709         adcwc++;
1710         fPayloadCurr++;
1711       }
1712
1713       if (adcwc != nADCwords)
1714         MCMError(kAdcDataAbort);
1715
1716       // adding index
1717       if (padcol > 0 && padcol < 144) {
1718         fSignalIndex->AddIndexRC(row, padcol);
1719       }
1720
1721       channelcount++;
1722     }
1723
1724     if (fCurrSm > -1 && fCurrSm < 18) {
1725       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNChannels += channelcount;
1726       fStats.fStatsSector[fCurrSm].fNChannels                      += channelcount;
1727     }
1728     if (channelcount != channelcountExp)
1729       MCMError(kAdcChannelsMiss);
1730
1731     mcmcount++;
1732     if (fCurrSm > -1 && fCurrSm < 18) {
1733       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNMCMs++;
1734       fStats.fStatsSector[fCurrSm].fNMCMs++;
1735     }
1736
1737     if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
1738       AliInfo(DumpRaw(Form("Event %i: Det %3i ROB %i MCM %2i", fRawReader->GetEventIndex(), fCurrHC/2, fCurrRobPos, fCurrMcmPos),
1739                       startPosMCM, fPayloadCurr - startPosMCM));
1740     }
1741
1742     // continue with next MCM
1743   }
1744
1745   // check for missing MCMs (if header suppression is inactive)
1746   if (((fCurrMajor & 0x1) == 0) && (mcmcount != mcmcountExp)) {
1747     LinkError(kMissMcmHeaders,
1748               "No. of MCM headers %i not as expected: %i",
1749               mcmcount, mcmcountExp);
1750   }
1751
1752   return (fPayloadCurr - start);
1753 }
1754
1755 Int_t AliTRDrawStream::ReadNonZSData()
1756 {
1757   // read the non-zs data from one link from the current reading position
1758
1759   UInt_t *start = fPayloadCurr;
1760
1761   Int_t mcmcount = 0;
1762   Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
1763   Int_t channelcount = 0;
1764   Int_t channelcountExp = 0;
1765   Int_t timebins;
1766   Int_t currentTimebin = 0;
1767   Int_t adcwc = 0;
1768   Int_t evno = -1;
1769   Int_t lastmcmpos = -1;
1770   Int_t lastrobpos = -1;
1771
1772   if (fCurrNtimebins != fNtimebins) {
1773     if (fNtimebins > 0)
1774       LinkError(kNtimebinsChanged,
1775                 "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
1776     fNtimebins = fCurrNtimebins;
1777   }
1778
1779   timebins = fNtimebins;
1780
1781   while (*(fPayloadCurr) != fgkDataEndmarker &&
1782          fPayloadCurr - fPayloadStart < fPayloadSize - 2) {
1783
1784     // ----- Checking MCM Header -----
1785     AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
1786
1787     // ----- checking for proper readout order - ROB -----
1788     fCurrRobPos = ROB(*fPayloadCurr);
1789     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1790       if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
1791         lastmcmpos = -1;
1792       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1793     }
1794     else {
1795       ROBError(kPosUnexp, Form("#%i after #%i in readout order", GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos));
1796     }
1797
1798     // ----- checking for proper readout order - MCM -----
1799     fCurrMcmPos = MCM(*fPayloadCurr);
1800     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
1801       lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
1802     }
1803     else {
1804       MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
1805     }
1806
1807     if (EvNo(*fPayloadCurr) != (evno & 0xfffff)) {
1808       if (evno == -1) {
1809         evno = EvNo(*fPayloadCurr);
1810       }
1811       else {
1812         MCMError(kEvCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
1813       }
1814     }
1815
1816     channelcount = 0;
1817     channelcountExp = 21;
1818     int channelno = -1;
1819
1820     Int_t adccoloff = AdcColOffset(*fPayloadCurr);
1821     Int_t padcoloff = PadColOffset(*fPayloadCurr);
1822     Int_t row = Row(*fPayloadCurr);
1823
1824     fPayloadCurr++;
1825
1826     // ----- reading marked ADC channels -----
1827     while (channelcount < channelcountExp &&
1828            *(fPayloadCurr) != fgkDataEndmarker) {
1829       if (channelno < 20)
1830         channelno++;
1831
1832       currentTimebin = 0;
1833
1834       adcwc = 0;
1835       Int_t nADCwords = (timebins + 2) / 3;
1836       AliDebug(2, Form("Now looking %i words", nADCwords));
1837       Int_t adccol = adccoloff - channelno;
1838       Int_t padcol = padcoloff - channelno;
1839       while ((adcwc < nADCwords) &&
1840              (*(fPayloadCurr) != fgkDataEndmarker) &&
1841              (fPayloadCurr - fPayloadStart < fPayloadSize)) {
1842         int check = 0x3 & *fPayloadCurr;
1843         if (channelno % 2 != 0) { // odd channel
1844           if (check != 0x2 && channelno < 21) {
1845             MCMError(kAdcCheckInvalid,
1846                      "%i for %2i. ADC word in odd channel %i",
1847                      check, adcwc+1, channelno);
1848           }
1849         }
1850         else {                  // even channel
1851           if (check != 0x3 && channelno < 21) {
1852             MCMError(kAdcCheckInvalid,
1853                      "%i for %2i. ADC word in even channel %i",
1854                      check, adcwc+1, channelno);
1855           }
1856         }
1857
1858         // filling the actual timebin data
1859         int tb2 = 0x3ff & *fPayloadCurr >> 22;
1860         int tb1 = 0x3ff & *fPayloadCurr >> 12;
1861         int tb0 = 0x3ff & *fPayloadCurr >> 2;
1862         if (adcwc != 0 || fCurrNtimebins <= 30)
1863           fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
1864         else
1865           tb0 = -1;
1866         if (currentTimebin >= fCurrNtimebins)
1867           break;
1868         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
1869         if (currentTimebin >= fCurrNtimebins)
1870           break;
1871         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
1872
1873         adcwc++;
1874         fPayloadCurr++;
1875       }
1876
1877       if (adcwc != nADCwords)
1878         MCMError(kAdcDataAbort);
1879
1880       // adding index
1881       if (padcol > 0 && padcol < 144) {
1882         fSignalIndex->AddIndexRC(row, padcol);
1883       }
1884
1885       channelcount++;
1886     }
1887
1888     if (channelcount != channelcountExp)
1889       MCMError(kAdcChannelsMiss);
1890     mcmcount++;
1891     // continue with next MCM
1892   }
1893
1894   // check for missing MCMs (if header suppression is inactive)
1895   if (mcmcount != mcmcountExp) {
1896     LinkError(kMissMcmHeaders,
1897               "%i not as expected: %i", mcmcount, mcmcountExp);
1898   }
1899
1900   return (fPayloadCurr - start);
1901 }
1902
1903 Int_t AliTRDrawStream::SeekNextStack()
1904 {
1905   // proceed in raw data stream till the next stack
1906
1907   if (!fCurrStackEndmarkerAvail)
1908     return 0;
1909
1910   UInt_t *start = fPayloadCurr;
1911
1912   // read until data endmarkers
1913   while ((fPayloadCurr - fPayloadStart < fPayloadSize-1) &&
1914          ((fPayloadCurr[0] != fgkStackEndmarker[0]) ||
1915           (fPayloadCurr[1] != fgkStackEndmarker[1])))
1916     fPayloadCurr++;
1917
1918   if ((fPayloadCurr - start) != 0)
1919     StackError(kUnknown, "skipped %i words to reach stack endmarker", fPayloadCurr - start);
1920
1921   AliDebug(2, Form("stack endmarker: 0x%08x 0x%08x", fPayloadCurr[0], fPayloadCurr[1]));
1922
1923   // goto next stack
1924   fPayloadCurr++;
1925   fPayloadCurr++;
1926
1927   return (fPayloadCurr-start);
1928 }
1929
1930 Int_t AliTRDrawStream::SeekNextLink()
1931 {
1932   // proceed in raw data stream till the next link
1933
1934   UInt_t *start = fPayloadCurr;
1935
1936   // read until data endmarkers
1937   while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1938          ((fPayloadCurr[0] != fgkStackEndmarker[0]) ||
1939           (fPayloadCurr[1] != fgkStackEndmarker[1])) &&
1940          *fPayloadCurr != fgkDataEndmarker)
1941     fPayloadCurr++;
1942
1943   // read all data endmarkers
1944   while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1945          *fPayloadCurr == fgkDataEndmarker)
1946     fPayloadCurr++;
1947
1948   return (fPayloadCurr - start);
1949 }
1950
1951 Bool_t AliTRDrawStream::ConnectTracklets(TTree *trklTree)
1952 {
1953   // connect the tracklet tree used to store the tracklet output
1954
1955   fTrackletTree = trklTree;
1956   if (!fTrackletTree)
1957     return kTRUE;
1958
1959   if (!fTrackletTree->GetBranch("hc"))
1960     fTrackletTree->Branch("hc", &fCurrHC, "hc/I");
1961   else
1962     fTrackletTree->SetBranchAddress("hc", &fCurrHC);
1963
1964   if (!fTrackletTree->GetBranch("trkl"))
1965     fTrackletTree->Branch("trkl", &fTrackletArray);
1966   else
1967     fTrackletTree->SetBranchAddress("trkl", &fTrackletArray);
1968
1969   return kTRUE;
1970 }
1971
1972
1973 void AliTRDrawStream::EquipmentError(ErrorCode_t err, const char *const msg, ...)
1974 {
1975   // register error according to error code on equipment level
1976   // and return the corresponding error message
1977
1978   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
1979   fLastError.fStack  = -1;
1980   fLastError.fLink   = -1;
1981   fLastError.fRob    = -1;
1982   fLastError.fMcm    = -1;
1983   fLastError.fError  = err;
1984   (this->*fStoreError)();
1985
1986   va_list ap;
1987   if (fgErrorDebugLevel[err] > 10)
1988     AliDebug(fgErrorDebugLevel[err],
1989              Form("Event %6i: Eq. %2d - %s : %s",
1990                   fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
1991                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1992   else
1993     AliError(Form("Event %6i: Eq. %2d - %s : %s",
1994                   fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
1995                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1996   fErrorFlags |= fgErrorBehav[err];
1997 }
1998
1999
2000 void AliTRDrawStream::StackError(ErrorCode_t err, const char *const msg, ...)
2001 {
2002   // register error according to error code on stack level
2003   // and return the corresponding error message
2004
2005   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
2006   fLastError.fStack  = fCurrSlot;
2007   fLastError.fLink   = -1;
2008   fLastError.fRob    = -1;
2009   fLastError.fMcm    = -1;
2010   fLastError.fError  = err;
2011   (this->*fStoreError)();
2012
2013   va_list ap;
2014   if (fgErrorDebugLevel[err] > 0)
2015     AliDebug(fgErrorDebugLevel[err],
2016              Form("Event %6i: Eq. %2d S %i - %s : %s",
2017                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
2018                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2019   else
2020     AliError(Form("Event %6i: Eq. %2d S %i - %s : %s",
2021                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
2022                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2023   fErrorFlags |= fgErrorBehav[err];
2024 }
2025
2026
2027 void AliTRDrawStream::LinkError(ErrorCode_t err, const char *const msg, ...)
2028 {
2029   // register error according to error code on link level
2030   // and return the corresponding error message
2031
2032   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
2033   fLastError.fStack  = fCurrSlot;
2034   fLastError.fLink   = fCurrLink;
2035   fLastError.fRob    = -1;
2036   fLastError.fMcm    = -1;
2037   fLastError.fError  = err;
2038   (this->*fStoreError)();
2039
2040   va_list ap;
2041   if (fgErrorDebugLevel[err] > 0)
2042     AliDebug(fgErrorDebugLevel[err],
2043              Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
2044                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
2045                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2046   else
2047     AliError(Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
2048                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
2049                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2050   fErrorFlags |= fgErrorBehav[err];
2051 }
2052
2053
2054 void AliTRDrawStream::ROBError(ErrorCode_t err, const char *const msg, ...)
2055 {
2056   // register error according to error code on ROB level
2057   // and return the corresponding error message
2058
2059   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
2060   fLastError.fStack  = fCurrSlot;
2061   fLastError.fLink   = fCurrLink;
2062   fLastError.fRob    = fCurrRobPos;
2063   fLastError.fMcm    = -1;
2064   fLastError.fError  = err;
2065   (this->*fStoreError)();
2066
2067   va_list ap;
2068   if (fgErrorDebugLevel[err] > 0)
2069     AliDebug(fgErrorDebugLevel[err],
2070              Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
2071                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
2072                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2073   else
2074     AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
2075                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
2076                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2077   fErrorFlags |= fgErrorBehav[err];
2078 }
2079
2080
2081 void AliTRDrawStream::MCMError(ErrorCode_t err, const char *const msg, ...)
2082 {
2083   // register error according to error code on MCM level
2084   // and return the corresponding error message
2085
2086   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
2087   fLastError.fStack  = fCurrSlot;
2088   fLastError.fLink   = fCurrLink;
2089   fLastError.fRob    = fCurrRobPos;
2090   fLastError.fMcm    = fCurrMcmPos;
2091   fLastError.fError  = err;
2092   (this->*fStoreError)();
2093
2094   va_list ap;
2095   if (fgErrorDebugLevel[err] > 0)
2096     AliDebug(fgErrorDebugLevel[err],
2097              Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
2098                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
2099                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2100   else
2101     AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
2102                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
2103                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2104   fErrorFlags |= fgErrorBehav[err];
2105 }
2106
2107 const char* AliTRDrawStream::GetErrorMessage(ErrorCode_t errCode)
2108 {
2109   // return the error message for the given error code
2110
2111   if (errCode > 0 && errCode < kLastErrorCode)
2112     return fgkErrorMessages[errCode];
2113   else
2114     return "";
2115 }
2116
2117 void AliTRDrawStream::AliTRDrawStats::ClearStats()
2118 {
2119   // clear statistics (includes clearing sector-wise statistics)
2120
2121   fBytesRead = 0;
2122   for (Int_t iSector = 0; iSector < 18; iSector++) {
2123     fStatsSector[iSector].ClearStats();
2124   }
2125
2126 }
2127
2128 void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::ClearStats()
2129 {
2130   // clear statistics (includes clearing HC-wise statistics)
2131
2132   fBytes = 0;
2133   fBytesRead = 0;
2134   fNTracklets = 0;
2135   fNMCMs = 0;
2136   fNChannels = 0;
2137
2138   for (Int_t iHC = 0; iHC < 60; iHC++) {
2139     fStatsHC[iHC].ClearStats();
2140   }
2141 }
2142
2143 void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::AliTRDrawStatsHC::ClearStats()
2144 {
2145   // clear statistics
2146
2147   fBytes = 0;
2148   fBytesRead = 0;
2149   fNTracklets = 0;
2150   fNMCMs = 0;
2151   fNChannels = 0;
2152 }
2153
2154 void AliTRDrawStream::SetDumpMCM(Int_t det, Int_t rob, Int_t mcm, Bool_t dump)
2155 {
2156   // mark MCM for dumping of raw data
2157
2158   if (dump) {
2159     fDumpMCM[fNDumpMCMs++] = (det << 7) | (rob << 4) | mcm;
2160   }
2161   else {
2162     Int_t iMCM;
2163     for (iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
2164       if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
2165         fNDumpMCMs--;
2166         break;
2167       }
2168     }
2169     for ( ; iMCM < fNDumpMCMs; iMCM++) {
2170       fDumpMCM[iMCM] = fDumpMCM[iMCM+1];
2171     }
2172   }
2173 }
2174
2175 Bool_t AliTRDrawStream::DumpingMCM(Int_t det, Int_t rob, Int_t mcm)  const
2176 {
2177   // check if MCM data should be dumped
2178
2179   for (Int_t iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
2180     if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
2181       return kTRUE;
2182     }
2183   }
2184   return kFALSE;
2185 }
2186
2187 TString AliTRDrawStream::DumpRaw(TString title, const UInt_t *start, Int_t length, UInt_t endmarker)
2188 {
2189   // dump raw data
2190
2191   title += "\n";
2192   for (Int_t pos = 0; pos < length; pos += 4) {
2193     if ((start[pos+0] != endmarker) && pos+0 < length)
2194       if ((start[pos+1] != endmarker && pos+1 < length))
2195         if ((start[pos+2] != endmarker && pos+2 < length))
2196           if ((start[pos+3] != endmarker && pos+3 < length))
2197             title += Form("   0x%08x 0x%08x 0x%08x 0x%08x\n",
2198                           start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
2199           else {
2200             title += Form("   0x%08x 0x%08x 0x%08x 0x%08x\n",
2201                           start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
2202             return title;
2203           }
2204         else {
2205           title += Form("   0x%08x 0x%08x 0x%08x\n",
2206                         start[pos+0], start[pos+1], start[pos+2]);
2207           return title;
2208         }
2209       else {
2210         title += Form("   0x%08x 0x%08x\n",
2211                       start[pos+0], start[pos+1]);
2212         return title;
2213       }
2214     else {
2215       title += Form("   0x%08x\n",
2216                     start[pos+0]);
2217       return title;
2218     }
2219   }
2220   return title;
2221 }
2222
2223 TString AliTRDrawStream::DumpMcmHeader(TString title, UInt_t word)
2224 {
2225   title += Form("0x%08x -> ROB: %i, MCM: %2i",
2226                 word, ROB(word), MCM(word));
2227   return title;
2228 }
2229
2230 TString AliTRDrawStream::DumpAdcMask(TString title, UInt_t word)
2231 {
2232   title += Form("0x%08x -> #ch : %2i, 0x%06x (%2i ch)",
2233                 word, GetNActiveChannels(word), GetActiveChannels(word), GetNActiveChannelsFromMask(word));
2234   return title;
2235 }
2236
2237 AliTRDrawStream::AliTRDrawStreamError::AliTRDrawStreamError(Int_t error, Int_t sector, Int_t stack, Int_t link, Int_t rob, Int_t mcm) :
2238   fError(error),
2239   fSector(sector),
2240   fStack(stack),
2241   fLink(link),
2242   fRob(rob),
2243   fMcm(mcm)
2244 {
2245   // ctor
2246
2247 }
2248
2249 void AliTRDrawStream::SortTracklets(TClonesArray *trklArray, TList &sortedTracklets, Int_t *indices)
2250 {
2251   // sort tracklets for referencing from GTU tracks
2252
2253   if (!trklArray)
2254     return;
2255
2256   Int_t nTracklets = trklArray->GetEntriesFast();
2257
2258   Int_t lastHC = -1;
2259   for (Int_t iTracklet = 0; iTracklet < nTracklets; iTracklet++) {
2260     AliTRDtrackletBase *trkl = (AliTRDtrackletBase*) ((*trklArray)[iTracklet]);
2261     Int_t hc = trkl->GetHCId();
2262     if ((hc < 0) || (hc >= 1080)) {
2263       AliErrorClass(Form("HC for tracklet: 0x%08x out of range: %i", trkl->GetTrackletWord(), trkl->GetHCId()));
2264       continue;
2265     }
2266     AliDebugClass(5, Form("hc: %4i : 0x%08x z: %2i", hc, trkl->GetTrackletWord(), trkl->GetZbin()));
2267     if (hc != lastHC) {
2268       AliDebugClass(2, Form("set tracklet index for HC %i to %i", hc, iTracklet));
2269       indices[hc] = iTracklet + 1;
2270       lastHC = hc;
2271     }
2272   }
2273
2274   for (Int_t iDet = 0; iDet < 540; iDet++) {
2275     Int_t trklIndexA = indices[2*iDet + 0] - 1;
2276     Int_t trklIndexB = indices[2*iDet + 1] - 1;
2277     Int_t trklIndex  = sortedTracklets.GetEntries();
2278     AliTRDtrackletBase *trklA = trklIndexA > -1 ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
2279     AliTRDtrackletBase *trklB = trklIndexB > -1 ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
2280     AliTRDtrackletBase *trklNext = 0x0;
2281     while (trklA != 0x0 || trklB != 0x0) {
2282       AliDebugClass(5, Form("det %i - A: %i/%i -> %p, B: %i/%i -> %p",
2283                        iDet, trklIndexA, nTracklets, trklA, trklIndexB, nTracklets, trklB));
2284       if (trklA == 0x0) {
2285         trklNext = trklB;
2286         trklIndexB++;
2287         trklB = trklIndexB < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
2288         if (trklB && trklB->GetHCId() != 2*iDet + 1)
2289           trklB = 0x0;
2290       }
2291       else if (trklB == 0x0) {
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         if (trklA->GetZbin() <= trklB->GetZbin()) {
2300           trklNext = trklA;
2301           trklIndexA++;
2302           trklA = trklIndexA < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
2303           if (trklA && trklA->GetHCId() != 2*iDet)
2304             trklA = 0x0;
2305         }
2306         else {
2307           trklNext = trklB;
2308           trklIndexB++;
2309           trklB = trklIndexB < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
2310           if (trklB && trklB->GetHCId() != 2*iDet + 1)
2311             trklB = 0x0;
2312         }
2313       }
2314       if (trklNext) {
2315         sortedTracklets.Add(trklNext);
2316
2317       }
2318     }
2319
2320     // updating tracklet indices as in output
2321     if (sortedTracklets.GetEntries() != trklIndex) {
2322       indices[2*iDet + 0] = trklIndex;
2323       indices[2*iDet + 1] = sortedTracklets.GetEntries();
2324     } else {
2325       indices[2*iDet + 0] = indices[2*iDet + 1] = -1;
2326     }
2327   }
2328 }
2329
2330 void AliTRDrawStream::AssignTracklets(AliESDTrdTrack *trdTrack, Int_t *trackletIndex, Int_t refIndex[6])
2331 {
2332   UInt_t mask  = trdTrack->GetLayerMask();
2333   UInt_t stack = trdTrack->GetStack();
2334
2335   for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
2336     refIndex[iLayer] = -1;
2337
2338     if (mask & (1 << iLayer)) {
2339
2340       Int_t det = trdTrack->GetSector()*30 + stack*6 + iLayer;
2341       Int_t idx = trdTrack->GetTrackletIndex(iLayer);
2342
2343       if ((det < 0) || (det > 539)) {
2344         AliErrorClass(Form("Invalid detector no. from track: %i", 2*det));
2345         continue;
2346       }
2347       if (trackletIndex[2*det] >= 0) {
2348         if ((trackletIndex[2*det] + idx > -1) &&
2349             (trackletIndex[2*det] + idx < trackletIndex[2*det+1])) {
2350           refIndex[iLayer] = trackletIndex[2*det] + idx;
2351         } else {
2352           AliErrorClass(Form("Requested tracklet index %i out of range", idx));
2353         }
2354       } else {
2355         AliErrorClass(Form("Non-existing tracklets requested in det %i", det));
2356       }
2357     }
2358   }
2359 }