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