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