- remove legacy code from TRD rawstream, e.g. writing of tracklets
[u/mrichter/AliRoot.git] / TRD / AliTRDrawStream.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 ////////////////////////////////////////////////////////////////////////////
17 //                                                                        //
18 //  Decoding data from the TRD raw stream                                 //
19 //  and translation into ADC values, on-line tracklets and tracks         //
20 //                                                                        //
21 //  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   return count;
1364 }
1365
1366 Int_t AliTRDrawStream::ReadTracklets()
1367 {
1368   // read the tracklets from one HC
1369
1370   Int_t nTracklets = 0;
1371
1372   UInt_t *start = fPayloadCurr;
1373   while (*(fPayloadCurr) != fgkTrackletEndmarker &&
1374          *(fPayloadCurr) != fgkStackEndmarker[0] &&
1375          *(fPayloadCurr) != fgkStackEndmarker[1] &&
1376          fPayloadCurr - fPayloadStart < (fPayloadSize - 1)) {
1377     ++nTracklets;
1378     if (fTracklets)
1379       new ((*fTracklets)[fTracklets->GetEntriesFast()]) AliTRDtrackletWord(*(fPayloadCurr), fCurrHC);
1380
1381     fPayloadCurr++;
1382   }
1383
1384   if (nTracklets > 0) {
1385     AliDebug(1, Form("Found %i tracklets in %i %i %i (ev. %i)", nTracklets,
1386                      (fCurrEquipmentId-kDDLOffset), fCurrSlot, fCurrLink, fRawReader->GetEventIndex()));
1387     if (fCurrSm > -1 && fCurrSm < 18) {
1388       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNTracklets += nTracklets;
1389       fStats.fStatsSector[fCurrSm].fNTracklets                      += nTracklets;
1390     }
1391   }
1392
1393   // loop over remaining tracklet endmarkers
1394   while ((*(fPayloadCurr) == fgkTrackletEndmarker &&
1395           fPayloadCurr - fPayloadStart < fPayloadSize))
1396     fPayloadCurr++;
1397
1398   return fPayloadCurr - start;
1399 }
1400
1401 Int_t AliTRDrawStream::ReadHcHeader()
1402 {
1403   // read and parse the HC header of one HC
1404   // and store the information in the corresponding variables
1405
1406   AliDebug(1, Form("HC header: 0x%08x", *fPayloadCurr));
1407   UInt_t *start = fPayloadCurr;
1408   // check not to be at the data endmarker
1409   if (*fPayloadCurr == fgkDataEndmarker ||
1410       *(fPayloadCurr) == fgkStackEndmarker[0] ||
1411       *(fPayloadCurr) == fgkStackEndmarker[1]) {
1412     LinkError(kHCmismatch, "found endmarker where HC header should be");
1413     return 0;
1414   }
1415
1416   fCurrSpecial    = (*fPayloadCurr >> 31) & 0x1;
1417   fCurrMajor      = (*fPayloadCurr >> 24) & 0x7f;
1418   fCurrMinor      = (*fPayloadCurr >> 17) & 0x7f;
1419   fCurrAddHcWords = (*fPayloadCurr >> 14) & 0x7;
1420   fCurrSm         = (*fPayloadCurr >> 9) & 0x1f;
1421   fCurrLayer      = (*fPayloadCurr >> 6) & 0x7;
1422   fCurrStack      = (*fPayloadCurr >> 3) & 0x7;
1423   fCurrSide       = (*fPayloadCurr >> 2) & 0x1;
1424   fCurrCheck      = (*fPayloadCurr) & 0x3;
1425
1426   if ((fCurrSm != (((Int_t) fCurrEquipmentId) - kDDLOffset)) ||
1427       (fCurrStack != fCurrSlot) ||
1428       (fCurrLayer != fCurrLink / 2) ||
1429       (fCurrSide != fCurrLink % 2)) {
1430     LinkError(kHCmismatch,
1431               "HC: %i, %i, %i, %i\n 0x%08x 0x%08x 0x%08x 0x%08x",
1432               fCurrSm, fCurrStack, fCurrLayer, fCurrSide,
1433               fPayloadCurr[0], fPayloadCurr[1], fPayloadCurr[2], fPayloadCurr[3]);
1434   }
1435   if (fCurrCheck != 0x1) {
1436     LinkError(kHCcheckFailed);
1437   }
1438
1439   if (fCurrAddHcWords > 0) {
1440     fCurrNtimebins = (fPayloadCurr[1] >> 26) & 0x3f;
1441 #ifdef TRD_RAW_DEBUG
1442     fCurrBC[fCurrHC] = (fPayloadCurr[1] >> 10) & 0xffff;
1443 #endif
1444     fCurrPtrgCnt = (fPayloadCurr[1] >> 6) & 0xf;
1445     fCurrPtrgPhase = (fPayloadCurr[1] >> 2) & 0xf;
1446   }
1447
1448   fPayloadCurr += 1 + fCurrAddHcWords;
1449
1450   return (fPayloadCurr - start);
1451 }
1452
1453 Int_t AliTRDrawStream::ReadTPData(Int_t mode)
1454 {
1455   // testing of testpattern 1 to 3 (hardcoded), 0 missing
1456   // evcnt checking missing
1457   Int_t cpu = 0;
1458   Int_t cpufromchannel[] = {0, 0, 0, 0, 0,  1, 1, 1, 1, 1,  2, 2, 2, 2, 2,  3, 3, 3, 3, 3, 3};
1459   Int_t evno  = -1;
1460   Int_t evcnt = 0;
1461   Int_t count = 0;
1462   Int_t mcmcount = -1;
1463   Int_t wordcount = 0;
1464   Int_t channelcount = 0;
1465   UInt_t expword = 0;
1466   UInt_t expadcval = 0;
1467   UInt_t diff = 0;
1468   Int_t lastmcmpos = -1;
1469   Int_t lastrobpos = -1;
1470
1471   UInt_t* start = fPayloadCurr;
1472
1473   while (*(fPayloadCurr) != fgkDataEndmarker &&
1474          fPayloadCurr - fPayloadStart < fPayloadSize - 1) {
1475
1476     // ----- Checking MCM Header -----
1477     AliDebug(2, DumpMcmHeader("MCM header: ", *fPayloadCurr));
1478     UInt_t *startPosMCM = fPayloadCurr;
1479     mcmcount++;
1480
1481     // ----- checking for proper readout order - ROB -----
1482     fCurrRobPos = ROB(*fPayloadCurr);
1483     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1484       if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
1485         lastmcmpos = -1;
1486       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1487     }
1488     else {
1489       ROBError(kPosUnexp, Form("#%i after #%i in readout order", GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos));
1490     }
1491
1492     // ----- checking for proper readout order - MCM -----
1493     fCurrMcmPos = MCM(*fPayloadCurr);
1494     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
1495       lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
1496     }
1497     else {
1498       MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
1499     }
1500
1501     if (EvNo(*fPayloadCurr) != (evno & 0xfffff)) {
1502       if (evno == -1) {
1503         evno = EvNo(*fPayloadCurr);
1504       }
1505       else {
1506         MCMError(kEvCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
1507 #ifdef TRD_RAW_DEBUG
1508         if (fCurrL0offset[fCurrHC/2] != 0)
1509           LinkError(kEvCntMismatch, "offset for %i %i %i changed from %i to %i = %i - %i",
1510                     fCurrEquipmentId, fCurrSlot, fCurrLink/2, fCurrL0offset[fCurrHC/2],
1511                     EvNo(*fPayloadCurr) - fCurrL0Count[fCurrEquipmentId-kDDLOffset],
1512                     EvNo(*fPayloadCurr), fCurrL0Count[fCurrEquipmentId-kDDLOffset]);
1513         fCurrL0offset[fCurrHC/2] = EvNo(*fPayloadCurr) - fCurrL0Count[fCurrEquipmentId-kDDLOffset];
1514         evno = fCurrL0Count[fCurrEquipmentId-kDDLOffset] + fCurrL0offset[fCurrHC/2];
1515 #endif
1516       }
1517     }
1518
1519     fPayloadCurr++;
1520
1521     evcnt = 0x3f & *fPayloadCurr >> 26;
1522     cpu = -1;
1523     channelcount = 0;
1524     while (channelcount < 21) {
1525       count = 0;
1526       if (cpu != cpufromchannel[channelcount]) {
1527         cpu = cpufromchannel[channelcount];
1528         expadcval = (1 << 9) | (fCurrRobPos << 6) | (fCurrMcmPos << 2) | cpu;
1529         wordcount = 0;
1530       }
1531
1532       while (count < 10) {
1533         if (*fPayloadCurr == fgkDataEndmarker) {
1534           MCMError(kMissTpData);
1535           return (fPayloadCurr - start);
1536         }
1537
1538         if (channelcount % 2 == 0)
1539           expword = 0x3;
1540         else
1541           expword = 0x2;
1542
1543         if (mode == 1) {
1544           // ----- TP 1 -----
1545           expword |= expadcval << 2;
1546           expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
1547           expword |= expadcval << 12;
1548           expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
1549           expword |= expadcval << 22;
1550           expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
1551         }
1552         else if (mode == 2) {
1553           // ----- TP 2 ------
1554           expword = ((0x3f & evcnt) << 26) | ((fCurrSm + 1) << 21) | ((fCurrLayer + 1) << 18) |
1555             ((fCurrStack + 1) << 15) |
1556             (fCurrRobPos << 12) | (fCurrMcmPos << 8) | (cpu << 6) | (wordcount + 1);
1557         }
1558         else if (mode == 3) {
1559           // ----- TP 3 -----
1560           expword = ((0xfff & evcnt) << 20) | (fCurrSm << 15) | (fCurrLink/2 << 12) | (fCurrStack << 9) |
1561             (fCurrRobPos << 6) | (fCurrMcmPos << 2) | (cpu << 0);
1562         }
1563         else {
1564           expword = 0;
1565           LinkError(kTPmodeInvalid, "Just reading");
1566         }
1567
1568         diff = *fPayloadCurr ^ expword;
1569         AliDebug(11, Form("Comparing ch %2i, word %2i (cpu %i): 0x%08x <-> 0x%08x",
1570                           channelcount, wordcount, cpu, *fPayloadCurr, expword));
1571
1572         if (diff != 0) {
1573           MCMError(kTPmismatch,
1574                    "Seen 0x%08x, expected 0x%08x, diff: 0x%08x, 0x%04x, 0x%02x - word %2i (cpu %i, ch %i)",
1575                    *fPayloadCurr, expword, diff,
1576                    0xffff & (diff | diff >> 16),
1577                    0xff & (diff | diff >> 8 | diff >> 16 | diff >> 24),
1578                    wordcount, cpu, channelcount);;
1579         }
1580         fPayloadCurr++;
1581         count++;
1582         wordcount++;
1583         if (*fPayloadCurr == fgkDataEndmarker)
1584           return (fPayloadCurr - start);
1585       }
1586       channelcount++;
1587     }
1588     // continue with next MCM
1589
1590     if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
1591       AliInfo(DumpRaw(Form("Event %i: Det %3i ROB %i MCM %2i", fRawReader->GetEventIndex(), fCurrHC/2, fCurrRobPos, fCurrMcmPos),
1592                       startPosMCM, fPayloadCurr - startPosMCM));
1593     }
1594
1595   }
1596   return fPayloadCurr - start;
1597 }
1598
1599
1600 Int_t AliTRDrawStream::ReadZSData()
1601 {
1602   // read the zs data from one link from the current reading position
1603
1604   UInt_t *start = fPayloadCurr;
1605
1606   Int_t mcmcount = 0;
1607   Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
1608   Int_t channelcount = 0;
1609   Int_t channelcountExp = 0;
1610   Int_t channelcountMax = 0;
1611   Int_t timebins;
1612   Int_t currentTimebin = 0;
1613   Int_t adcwc = 0;
1614   Int_t evno = -1;
1615   Int_t lastmcmpos = -1;
1616   Int_t lastrobpos = -1;
1617
1618   if (fCurrNtimebins != fNtimebins) {
1619     if (fNtimebins > 0)
1620       LinkError(kNtimebinsChanged,
1621                 "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
1622     fNtimebins = fCurrNtimebins;
1623   }
1624
1625   timebins = fNtimebins;
1626
1627   while (*(fPayloadCurr) != fgkDataEndmarker &&
1628          *(fPayloadCurr) != fgkStackEndmarker[0] &&
1629          *(fPayloadCurr) != fgkStackEndmarker[1] &&
1630          fPayloadCurr - fPayloadStart < fPayloadSize) {
1631
1632     // ----- Checking MCM Header -----
1633     AliDebug(2, DumpMcmHeader("MCM header: ", *fPayloadCurr));
1634     UInt_t *startPosMCM = fPayloadCurr;
1635
1636     // ----- checking for proper readout order - ROB -----
1637     fCurrRobPos = ROB(*fPayloadCurr);
1638     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1639       if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
1640         lastmcmpos = -1;
1641       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1642     }
1643     else {
1644       ROBError(kPosUnexp, Form("#%i after #%i and #%i in readout order",
1645                                GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos, GetROBReadoutPos(fCurrRobPos)));
1646     }
1647
1648     // ----- checking for proper readout order - MCM -----
1649     fCurrMcmPos = MCM(*fPayloadCurr);
1650     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
1651       lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
1652     }
1653     else {
1654       MCMError(kPosUnexp, Form("#%i after #%i and #%i in readout order",
1655                                GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos, GetMCMReadoutPos(fCurrMcmPos)));
1656     }
1657
1658 #ifdef TRD_RAW_DEBUG
1659     if (fCurrL0Count[fCurrEquipmentId-kDDLOffset] > 0) {
1660       evno = fCurrL0Count[fCurrEquipmentId-kDDLOffset] + fCurrL0offset[fCurrHC/2];
1661     }
1662     fCurrEvCount[fCurrEquipmentId-kDDLOffset] = EvNo(*fPayloadCurr);
1663 #endif
1664
1665     if (EvNo(*fPayloadCurr) != (evno & 0xfffff)) {
1666       if (evno == -1) {
1667         evno = EvNo(*fPayloadCurr);
1668       }
1669       else {
1670         MCMError(kEvCntMismatch, "exp <-> SM: %i <-> %i", evno & 0xfffff, EvNo(*fPayloadCurr));
1671 #ifdef TRD_RAW_DEBUG
1672         Int_t prevOffset = fCurrL0offset[fCurrHC/2];
1673         fCurrL0offset[fCurrHC/2] = (- fCurrL0Count[fCurrEquipmentId-kDDLOffset] + EvNo(*fPayloadCurr)) % (1 << 20);
1674         if (fCurrL0offset[fCurrHC/2] < 0)
1675           fCurrL0offset[fCurrHC/2] += 0xfffff;
1676         evno = (fCurrL0Count[fCurrEquipmentId-kDDLOffset] + fCurrL0offset[fCurrHC/2]) & 0xfffff;
1677         if (prevOffset != 0)
1678           LinkError(kEvCntMismatch, "offset for %i %i %i changed from %i to %i = %i - %i",
1679                     fCurrEquipmentId, fCurrSlot, fCurrLink/2,
1680                     prevOffset,
1681                     fCurrL0offset[fCurrHC/2],
1682                     fCurrL0Count[fCurrEquipmentId-kDDLOffset],
1683                     EvNo(*fPayloadCurr));
1684 #endif
1685       }
1686     }
1687     Int_t adccoloff = AdcColOffset(*fPayloadCurr);
1688     Int_t padcoloff = PadColOffset(*fPayloadCurr);
1689     Int_t row = Row(*fPayloadCurr);
1690     fPayloadCurr++;
1691
1692     if ((row > 11) && (fCurrStack == 2)) {
1693       MCMError(kInvalidPadRow, "Data in padrow > 11 for stack 2");
1694     }
1695
1696     if (fErrorFlags & (kDiscardHC | kDiscardDDL))
1697       break;
1698
1699     // ----- Reading ADC channels -----
1700     AliDebug(2, DumpAdcMask("ADC mask: ", *fPayloadCurr));
1701
1702     // ----- analysing the ADC mask -----
1703     channelcount = 0;
1704     channelcountExp = GetNActiveChannelsFromMask(*fPayloadCurr);
1705     channelcountMax = GetNActiveChannels(*fPayloadCurr);
1706     Int_t channelmask = GetActiveChannels(*fPayloadCurr);
1707     Int_t channelno = -1;
1708     fPayloadCurr++;
1709
1710     if (channelcountExp != channelcountMax) {
1711       if (channelcountExp > channelcountMax) {
1712         Int_t temp = channelcountExp;
1713         channelcountExp = channelcountMax;
1714         channelcountMax = temp;
1715       }
1716       while (channelcountExp < channelcountMax && channelcountExp < 21 &&
1717              fPayloadCurr - fPayloadStart < fPayloadSize - 10 * channelcountExp - 1) {
1718         MCMError(kAdcMaskInconsistent,
1719                  "Possible MCM-H: 0x%08x, possible ADC-mask: 0x%08x",
1720                  *(fPayloadCurr + 10 * channelcountExp),
1721                  *(fPayloadCurr + 10 * channelcountExp + 1) );
1722         if (!CouldBeMCMhdr( *(fPayloadCurr + 10 * channelcountExp)) && !CouldBeADCmask( *(fPayloadCurr + 10 * channelcountExp + 1)))
1723           channelcountExp++;
1724         else {
1725           break;
1726         }
1727       }
1728       MCMError(kAdcMaskInconsistent,
1729                "Inconsistency in no. of active channels: Counter: %i, Mask: %i, chosen: %i!",
1730                GetNActiveChannels(fPayloadCurr[-1]), GetNActiveChannelsFromMask(fPayloadCurr[-1]), channelcountExp);
1731     }
1732     AliDebug(2, Form("expecting %i active channels, %i timebins", channelcountExp, fCurrNtimebins));
1733
1734     // ----- reading marked ADC channels -----
1735     while (channelcount < channelcountExp && *(fPayloadCurr) != fgkDataEndmarker) {
1736       if (channelno < 20)
1737         channelno++;
1738       while (channelno < 20 && (channelmask & 1 << channelno) == 0)
1739         channelno++;
1740
1741       if (fCurrNtimebins > 30) {
1742         currentTimebin = ((*fPayloadCurr >> 2) & 0x3f);
1743         timebins = ((*fPayloadCurr >> 8) & 0xf) * 3;
1744       }
1745       else {
1746         currentTimebin = 0;
1747       }
1748
1749       adcwc = 0;
1750       Int_t nADCwords = (timebins + 2) / 3;
1751       AliDebug(3, Form("Now reading %i words for channel %2i", nADCwords, channelno));
1752       Int_t adccol = adccoloff - channelno;
1753       Int_t padcol = padcoloff - channelno;
1754 //      if (adccol < 3 || adccol > 165)
1755 //      AliInfo(Form("writing channel %i of det %3i %i:%2i to adcrow/-col: %i/%i padcol: %i",
1756 //                   channelno, fCurrHC/2, fCurrRobPos, fCurrMcmPos, row, adccol, padcol));
1757
1758       while ((adcwc < nADCwords) &&
1759              (*(fPayloadCurr) != fgkDataEndmarker) &&
1760              (fPayloadCurr - fPayloadStart < fPayloadSize)) {
1761         int check = 0x3 & *fPayloadCurr;
1762         if (channelno % 2 != 0) { // odd channel
1763           if (check != 0x2 && channelno < 21) {
1764             MCMError(kAdcCheckInvalid,
1765                      "%i for %2i. ADC word in odd channel %i",
1766                      check, adcwc+1, channelno);
1767           }
1768         }
1769         else {                  // even channel
1770           if (check != 0x3 && channelno < 21) {
1771             MCMError(kAdcCheckInvalid,
1772                      "%i for %2i. ADC word in even channel %i",
1773                      check, adcwc+1, channelno);
1774           }
1775         }
1776
1777         if ((fErrorFlags & kDiscardMCM) == 0) {
1778           // filling the actual timebin data
1779           int tb2 = 0x3ff & (*fPayloadCurr >> 22);
1780           int tb1 = 0x3ff & (*fPayloadCurr >> 12);
1781           int tb0 = 0x3ff & (*fPayloadCurr >>  2);
1782           if (adcwc != 0 || fCurrNtimebins <= 30)
1783             fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
1784           else
1785             tb0 = -1;
1786           if (currentTimebin < fCurrNtimebins)
1787             fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
1788           if (currentTimebin < fCurrNtimebins)
1789             fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
1790         }
1791
1792         adcwc++;
1793         fPayloadCurr++;
1794       }
1795
1796       if (adcwc != nADCwords)
1797         MCMError(kAdcDataAbort);
1798
1799       // adding index
1800       if (padcol > 0 && padcol < 144) {
1801         fSignalIndex->AddIndexRC(row, padcol);
1802       }
1803
1804       channelcount++;
1805     }
1806
1807     if (fCurrSm > -1 && fCurrSm < 18) {
1808       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNChannels += channelcount;
1809       fStats.fStatsSector[fCurrSm].fNChannels                      += channelcount;
1810     }
1811     if (channelcount != channelcountExp)
1812       MCMError(kAdcChannelsMiss);
1813
1814     mcmcount++;
1815     if (fCurrSm > -1 && fCurrSm < 18) {
1816       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNMCMs++;
1817       fStats.fStatsSector[fCurrSm].fNMCMs++;
1818     }
1819
1820     if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
1821       AliInfo(DumpRaw(Form("Event %i: Det %3i ROB %i MCM %2i", fRawReader->GetEventIndex(), fCurrHC/2, fCurrRobPos, fCurrMcmPos),
1822                       startPosMCM, fPayloadCurr - startPosMCM));
1823     }
1824
1825     // continue with next MCM
1826   }
1827
1828   // check for missing MCMs (if header suppression is inactive)
1829   if (((fCurrMajor & 0x1) == 0) && (mcmcount != mcmcountExp)) {
1830     LinkError(kMissMcmHeaders,
1831               "No. of MCM headers %i not as expected: %i",
1832               mcmcount, mcmcountExp);
1833   }
1834
1835   return (fPayloadCurr - start);
1836 }
1837
1838 Int_t AliTRDrawStream::ReadNonZSData()
1839 {
1840   // read the non-zs data from one link from the current reading position
1841
1842   UInt_t *start = fPayloadCurr;
1843
1844   Int_t mcmcount = 0;
1845   Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
1846   Int_t channelcount = 0;
1847   Int_t channelcountExp = 0;
1848   Int_t timebins;
1849   Int_t currentTimebin = 0;
1850   Int_t adcwc = 0;
1851   Int_t evno = -1;
1852   Int_t lastmcmpos = -1;
1853   Int_t lastrobpos = -1;
1854
1855   if (fCurrNtimebins != fNtimebins) {
1856     if (fNtimebins > 0)
1857       LinkError(kNtimebinsChanged,
1858                 "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
1859     fNtimebins = fCurrNtimebins;
1860   }
1861
1862   timebins = fNtimebins;
1863
1864   while (*(fPayloadCurr) != fgkDataEndmarker &&
1865          fPayloadCurr - fPayloadStart < fPayloadSize - 2) {
1866
1867     // ----- Checking MCM Header -----
1868     AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
1869
1870     // ----- checking for proper readout order - ROB -----
1871     fCurrRobPos = ROB(*fPayloadCurr);
1872     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1873       if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
1874         lastmcmpos = -1;
1875       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1876     }
1877     else {
1878       ROBError(kPosUnexp, Form("#%i after #%i in readout order", GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos));
1879     }
1880
1881     // ----- checking for proper readout order - MCM -----
1882     fCurrMcmPos = MCM(*fPayloadCurr);
1883     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
1884       lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
1885     }
1886     else {
1887       MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
1888     }
1889
1890     if (EvNo(*fPayloadCurr) != (evno & 0xfffff)) {
1891       if (evno == -1) {
1892         evno = EvNo(*fPayloadCurr);
1893       }
1894       else {
1895         MCMError(kEvCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
1896 #ifdef TRD_RAW_DEBUG
1897         if (fCurrL0offset[fCurrHC/2] != 0)
1898           LinkError(kEvCntMismatch, "offset for %i %i %i changed from %i to %i = %i - %i",
1899                     fCurrEquipmentId, fCurrSlot, fCurrLink/2, fCurrL0offset[fCurrHC/2],
1900                     EvNo(*fPayloadCurr) - fCurrL0Count[fCurrEquipmentId-kDDLOffset],
1901                     EvNo(*fPayloadCurr), fCurrL0Count[fCurrEquipmentId-kDDLOffset]);
1902         fCurrL0offset[fCurrHC/2] = EvNo(*fPayloadCurr) - fCurrL0Count[fCurrEquipmentId-kDDLOffset];
1903         evno = fCurrL0Count[fCurrEquipmentId-kDDLOffset] + fCurrL0offset[fCurrHC/2];
1904 #endif
1905       }
1906     }
1907
1908     channelcount = 0;
1909     channelcountExp = 21;
1910     int channelno = -1;
1911
1912     Int_t adccoloff = AdcColOffset(*fPayloadCurr);
1913     Int_t padcoloff = PadColOffset(*fPayloadCurr);
1914     Int_t row = Row(*fPayloadCurr);
1915     fPayloadCurr++;
1916
1917     if ((row > 11) && (fCurrStack == 2)) {
1918       MCMError(kInvalidPadRow, "Data in padrow > 11 for stack 2");
1919     }
1920
1921     if (fErrorFlags & (kDiscardHC | kDiscardDDL))
1922       break;
1923
1924     // ----- reading marked ADC channels -----
1925     while (channelcount < channelcountExp &&
1926            *(fPayloadCurr) != fgkDataEndmarker) {
1927       if (channelno < 20)
1928         channelno++;
1929
1930       currentTimebin = 0;
1931
1932       adcwc = 0;
1933       Int_t nADCwords = (timebins + 2) / 3;
1934       AliDebug(2, Form("Now looking %i words", nADCwords));
1935       Int_t adccol = adccoloff - channelno;
1936       Int_t padcol = padcoloff - channelno;
1937       while ((adcwc < nADCwords) &&
1938              (*(fPayloadCurr) != fgkDataEndmarker) &&
1939              (fPayloadCurr - fPayloadStart < fPayloadSize)) {
1940         int check = 0x3 & *fPayloadCurr;
1941         if (channelno % 2 != 0) { // odd channel
1942           if (check != 0x2 && channelno < 21) {
1943             MCMError(kAdcCheckInvalid,
1944                      "%i for %2i. ADC word in odd channel %i",
1945                      check, adcwc+1, channelno);
1946           }
1947         }
1948         else {                  // even channel
1949           if (check != 0x3 && channelno < 21) {
1950             MCMError(kAdcCheckInvalid,
1951                      "%i for %2i. ADC word in even channel %i",
1952                      check, adcwc+1, channelno);
1953           }
1954         }
1955
1956         if ((fErrorFlags & kDiscardMCM) == 0) {
1957           // filling the actual timebin data
1958           int tb2 = 0x3ff & (*fPayloadCurr >> 22);
1959           int tb1 = 0x3ff & (*fPayloadCurr >> 12);
1960           int tb0 = 0x3ff & (*fPayloadCurr >>  2);
1961           if (adcwc != 0 || fCurrNtimebins <= 30)
1962             fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
1963           else
1964             tb0 = -1;
1965           if (currentTimebin < fCurrNtimebins)
1966             fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
1967           if (currentTimebin < fCurrNtimebins)
1968             fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
1969         }
1970
1971         adcwc++;
1972         fPayloadCurr++;
1973       }
1974
1975       if (adcwc != nADCwords)
1976         MCMError(kAdcDataAbort);
1977
1978       // adding index
1979       if (padcol > 0 && padcol < 144) {
1980         fSignalIndex->AddIndexRC(row, padcol);
1981       }
1982
1983       channelcount++;
1984     }
1985
1986     if (channelcount != channelcountExp)
1987       MCMError(kAdcChannelsMiss);
1988     mcmcount++;
1989     // continue with next MCM
1990   }
1991
1992   // check for missing MCMs (if header suppression is inactive)
1993   if (mcmcount != mcmcountExp) {
1994     LinkError(kMissMcmHeaders,
1995               "%i not as expected: %i", mcmcount, mcmcountExp);
1996   }
1997
1998   return (fPayloadCurr - start);
1999 }
2000
2001 #ifdef TRD_RAW_CRC
2002 UShort_t AliTRDrawStream::CalcLinkChecksum(UInt_t *data, Int_t size)
2003 {
2004   // calculate the CRC for the data from this link
2005   // must not change the pointers to the data
2006
2007   // always count two endmarkers
2008   Int_t nEndmarkers = 0;
2009   for (Int_t i = 0; i < size; i++) {
2010     if (data[size-1 - i] != fgkDataEndmarker)
2011       break;
2012     nEndmarkers++;
2013   }
2014
2015   size = size - (nEndmarkers-2);
2016
2017   boost::crc_optimal<16, 0x8005, 0, 0, false, false> checksumLink;
2018
2019   checksumLink.reset();
2020   checksumLink.process_bytes(data, size*sizeof(UInt_t));
2021   return checksumLink();
2022 }
2023 #else
2024 UShort_t AliTRDrawStream::CalcLinkChecksum(UInt_t * /* data */, Int_t /* size */)
2025 {
2026   // checksum calculation relies on boost,
2027   // we return 0 if we cannot calculate it
2028
2029   AliError("Checksum calculation relies on boost CRC implementation!");
2030
2031   return 0;
2032 }
2033 #endif
2034
2035 Int_t AliTRDrawStream::SeekNextStack()
2036 {
2037   // proceed in raw data stream till the next stack
2038
2039   if (!fCurrStackEndmarkerAvail)
2040     return 0;
2041
2042   UInt_t *start = fPayloadCurr;
2043
2044   // read until data endmarkers
2045   while ((fPayloadCurr - fPayloadStart < fPayloadSize-1) &&
2046          ((fPayloadCurr[0] != fgkStackEndmarker[0]) ||
2047           (fPayloadCurr[1] != fgkStackEndmarker[1])))
2048     fPayloadCurr++;
2049
2050   if ((fPayloadCurr - start) != 0)
2051     StackError(kUnknown, "skipped %i words to reach stack endmarker", fPayloadCurr - start);
2052
2053   AliDebug(2, Form("stack endmarker: 0x%08x 0x%08x", fPayloadCurr[0], fPayloadCurr[1]));
2054
2055   // goto next stack
2056   fPayloadCurr++;
2057   fPayloadCurr++;
2058
2059   return (fPayloadCurr-start);
2060 }
2061
2062 Int_t AliTRDrawStream::SeekNextLink()
2063 {
2064   // proceed in raw data stream till the next link
2065
2066   UInt_t *start = fPayloadCurr;
2067
2068   // read until data endmarkers
2069   while (fPayloadCurr - fPayloadStart < fPayloadSize &&
2070          ((fPayloadCurr[0] != fgkStackEndmarker[0]) ||
2071           (fPayloadCurr[1] != fgkStackEndmarker[1])) &&
2072          *fPayloadCurr != fgkDataEndmarker)
2073     fPayloadCurr++;
2074
2075   // read all data endmarkers
2076   while (fPayloadCurr - fPayloadStart < fPayloadSize &&
2077          *fPayloadCurr == fgkDataEndmarker)
2078     fPayloadCurr++;
2079
2080   return (fPayloadCurr - start);
2081 }
2082
2083
2084 void AliTRDrawStream::EquipmentError(ErrorCode_t err, const char *const msg, ...)
2085 {
2086   // register error according to error code on equipment level
2087   // and return the corresponding error message
2088
2089   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
2090   fLastError.fStack  = -1;
2091   fLastError.fLink   = -1;
2092   fLastError.fRob    = -1;
2093   fLastError.fMcm    = -1;
2094   fLastError.fError  = err;
2095   (this->*fStoreError)();
2096
2097   va_list ap;
2098   if (fgErrorDebugLevel[err] > 10)
2099     AliDebug(fgErrorDebugLevel[err],
2100              Form("Event %6i: Eq. %2d - %s : %s",
2101                   fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
2102                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2103   else
2104     AliError(Form("Event %6i: Eq. %2d - %s : %s",
2105                   fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
2106                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2107   fErrorFlags |= fgErrorBehav[err];
2108 }
2109
2110
2111 void AliTRDrawStream::StackError(ErrorCode_t err, const char *const msg, ...)
2112 {
2113   // register error according to error code on stack level
2114   // and return the corresponding error message
2115
2116   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
2117   fLastError.fStack  = fCurrSlot;
2118   fLastError.fLink   = -1;
2119   fLastError.fRob    = -1;
2120   fLastError.fMcm    = -1;
2121   fLastError.fError  = err;
2122   (this->*fStoreError)();
2123
2124   va_list ap;
2125   if (fgErrorDebugLevel[err] > 0)
2126     AliDebug(fgErrorDebugLevel[err],
2127              Form("Event %6i: Eq. %2d S %i - %s : %s",
2128                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
2129                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2130   else
2131     AliError(Form("Event %6i: Eq. %2d S %i - %s : %s",
2132                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
2133                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2134   fErrorFlags |= fgErrorBehav[err];
2135 }
2136
2137
2138 void AliTRDrawStream::LinkError(ErrorCode_t err, const char *const msg, ...)
2139 {
2140   // register error according to error code on link level
2141   // and return the corresponding error message
2142
2143   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
2144   fLastError.fStack  = fCurrSlot;
2145   fLastError.fLink   = fCurrLink;
2146   fLastError.fRob    = -1;
2147   fLastError.fMcm    = -1;
2148   fLastError.fError  = err;
2149   (this->*fStoreError)();
2150
2151   va_list ap;
2152   if (fgErrorDebugLevel[err] > 0)
2153     AliDebug(fgErrorDebugLevel[err],
2154              Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
2155                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
2156                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2157   else
2158     AliError(Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
2159                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
2160                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2161   fErrorFlags |= fgErrorBehav[err];
2162 }
2163
2164
2165 void AliTRDrawStream::ROBError(ErrorCode_t err, const char *const msg, ...)
2166 {
2167   // register error according to error code on ROB level
2168   // and return the corresponding error message
2169
2170   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
2171   fLastError.fStack  = fCurrSlot;
2172   fLastError.fLink   = fCurrLink;
2173   fLastError.fRob    = fCurrRobPos;
2174   fLastError.fMcm    = -1;
2175   fLastError.fError  = err;
2176   (this->*fStoreError)();
2177
2178   va_list ap;
2179   if (fgErrorDebugLevel[err] > 0)
2180     AliDebug(fgErrorDebugLevel[err],
2181              Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
2182                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
2183                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2184   else
2185     AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
2186                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
2187                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2188   fErrorFlags |= fgErrorBehav[err];
2189 }
2190
2191
2192 void AliTRDrawStream::MCMError(ErrorCode_t err, const char *const msg, ...)
2193 {
2194   // register error according to error code on MCM level
2195   // and return the corresponding error message
2196
2197   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
2198   fLastError.fStack  = fCurrSlot;
2199   fLastError.fLink   = fCurrLink;
2200   fLastError.fRob    = fCurrRobPos;
2201   fLastError.fMcm    = fCurrMcmPos;
2202   fLastError.fError  = err;
2203   (this->*fStoreError)();
2204
2205   va_list ap;
2206   if (fgErrorDebugLevel[err] > 0)
2207     AliDebug(fgErrorDebugLevel[err],
2208              Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
2209                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
2210                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2211   else
2212     AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
2213                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
2214                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
2215   fErrorFlags |= fgErrorBehav[err];
2216 }
2217
2218 const char* AliTRDrawStream::GetErrorMessage(ErrorCode_t errCode)
2219 {
2220   // return the error message for the given error code
2221
2222   if (errCode > 0 && errCode < kLastErrorCode)
2223     return fgkErrorMessages[errCode];
2224   else
2225     return "";
2226 }
2227
2228 void AliTRDrawStream::AliTRDrawStats::ClearStats()
2229 {
2230   // clear statistics (includes clearing sector-wise statistics)
2231
2232   fBytesRead = 0;
2233   for (Int_t iSector = 0; iSector < 18; iSector++) {
2234     fStatsSector[iSector].ClearStats();
2235   }
2236
2237 }
2238
2239 void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::ClearStats()
2240 {
2241   // clear statistics (includes clearing HC-wise statistics)
2242
2243   fBytes = 0;
2244   fBytesRead = 0;
2245   fNTracklets = 0;
2246   fNMCMs = 0;
2247   fNChannels = 0;
2248
2249   for (Int_t iHC = 0; iHC < 60; iHC++) {
2250     fStatsHC[iHC].ClearStats();
2251   }
2252 }
2253
2254 void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::AliTRDrawStatsHC::ClearStats()
2255 {
2256   // clear statistics
2257
2258   fBytes = 0;
2259   fBytesRead = 0;
2260   fNTracklets = 0;
2261   fNMCMs = 0;
2262   fNChannels = 0;
2263 }
2264
2265 void AliTRDrawStream::SetDumpMCM(Int_t det, Int_t rob, Int_t mcm, Bool_t dump)
2266 {
2267   // mark MCM for dumping of raw data
2268
2269   if (dump) {
2270     fDumpMCM[fNDumpMCMs++] = (det << 7) | (rob << 4) | mcm;
2271   }
2272   else {
2273     Int_t iMCM;
2274     for (iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
2275       if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
2276         fNDumpMCMs--;
2277         break;
2278       }
2279     }
2280     for ( ; iMCM < fNDumpMCMs; iMCM++) {
2281       fDumpMCM[iMCM] = fDumpMCM[iMCM+1];
2282     }
2283   }
2284 }
2285
2286 Bool_t AliTRDrawStream::DumpingMCM(Int_t det, Int_t rob, Int_t mcm)  const
2287 {
2288   // check if MCM data should be dumped
2289
2290   for (Int_t iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
2291     if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
2292       return kTRUE;
2293     }
2294   }
2295   return kFALSE;
2296 }
2297
2298 TString AliTRDrawStream::DumpRaw(TString title, const UInt_t *start, Int_t length, UInt_t endmarker)
2299 {
2300   // dump raw data
2301
2302   title += "\n";
2303   for (Int_t pos = 0; pos < length; pos += 4) {
2304     if ((start[pos+0] != endmarker) && pos+0 < length)
2305       if ((start[pos+1] != endmarker && pos+1 < length))
2306         if ((start[pos+2] != endmarker && pos+2 < length))
2307           if ((start[pos+3] != endmarker && pos+3 < length))
2308             title += Form("   0x%08x 0x%08x 0x%08x 0x%08x\n",
2309                           start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
2310           else {
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             return title;
2314           }
2315         else {
2316           title += Form("   0x%08x 0x%08x 0x%08x\n",
2317                         start[pos+0], start[pos+1], start[pos+2]);
2318           return title;
2319         }
2320       else {
2321         title += Form("   0x%08x 0x%08x\n",
2322                       start[pos+0], start[pos+1]);
2323         return title;
2324       }
2325     else {
2326       title += Form("   0x%08x\n",
2327                     start[pos+0]);
2328       return title;
2329     }
2330   }
2331   return title;
2332 }
2333
2334 TString AliTRDrawStream::DumpMcmHeader(TString title, UInt_t word)
2335 {
2336   title += Form("0x%08x -> ROB: %i, MCM: %2i",
2337                 word, ROB(word), MCM(word));
2338   return title;
2339 }
2340
2341 TString AliTRDrawStream::DumpAdcMask(TString title, UInt_t word)
2342 {
2343   title += Form("0x%08x -> #ch : %2i, 0x%06x (%2i ch)",
2344                 word, GetNActiveChannels(word), GetActiveChannels(word), GetNActiveChannelsFromMask(word));
2345   return title;
2346 }
2347
2348 AliTRDrawStream::AliTRDrawStreamError::AliTRDrawStreamError(Int_t error, Int_t sector, Int_t stack, Int_t link, Int_t rob, Int_t mcm) :
2349   fError(error),
2350   fSector(sector),
2351   fStack(stack),
2352   fLink(link),
2353   fRob(rob),
2354   fMcm(mcm)
2355 {
2356   // ctor
2357
2358 }
2359
2360 void AliTRDrawStream::SortTracklets(TClonesArray *trklArray, TList &sortedTracklets, Int_t *indices)
2361 {
2362   // sort tracklets for referencing from GTU tracks
2363
2364   if (!trklArray)
2365     return;
2366
2367   Int_t nTracklets = trklArray->GetEntriesFast();
2368
2369   Int_t lastHC = -1;
2370   for (Int_t iTracklet = 0; iTracklet < nTracklets; iTracklet++) {
2371     AliTRDtrackletBase *trkl = (AliTRDtrackletBase*) ((*trklArray)[iTracklet]);
2372     Int_t hc = trkl->GetHCId();
2373     if ((hc < 0) || (hc >= 1080)) {
2374       AliErrorClass(Form("HC for tracklet: 0x%08x out of range: %i", trkl->GetTrackletWord(), trkl->GetHCId()));
2375       continue;
2376     }
2377     AliDebugClass(5, Form("hc: %4i : 0x%08x z: %2i", hc, trkl->GetTrackletWord(), trkl->GetZbin()));
2378     if (hc != lastHC) {
2379       AliDebugClass(2, Form("set tracklet index for HC %i to %i", hc, iTracklet));
2380       indices[hc] = iTracklet + 1;
2381       lastHC = hc;
2382     }
2383   }
2384
2385   for (Int_t iDet = 0; iDet < 540; iDet++) {
2386     Int_t trklIndexA = indices[2*iDet + 0] - 1;
2387     Int_t trklIndexB = indices[2*iDet + 1] - 1;
2388     Int_t trklIndex  = sortedTracklets.GetEntries();
2389     AliTRDtrackletBase *trklA = trklIndexA > -1 ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
2390     AliTRDtrackletBase *trklB = trklIndexB > -1 ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
2391     AliTRDtrackletBase *trklNext = 0x0;
2392     while (trklA != 0x0 || trklB != 0x0) {
2393       AliDebugClass(5, Form("det %i - A: %i/%i -> %p, B: %i/%i -> %p",
2394                        iDet, trklIndexA, nTracklets, trklA, trklIndexB, nTracklets, trklB));
2395       if (trklA == 0x0) {
2396         trklNext = trklB;
2397         trklIndexB++;
2398         trklB = trklIndexB < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
2399         if (trklB && trklB->GetHCId() != 2*iDet + 1)
2400           trklB = 0x0;
2401       }
2402       else if (trklB == 0x0) {
2403         trklNext = trklA;
2404         trklIndexA++;
2405         trklA = trklIndexA < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
2406         if (trklA && trklA->GetHCId() != 2*iDet)
2407           trklA = 0x0;
2408       }
2409       else {
2410         if (trklA->GetZbin() <= trklB->GetZbin()) {
2411           trklNext = trklA;
2412           trklIndexA++;
2413           trklA = trklIndexA < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
2414           if (trklA && trklA->GetHCId() != 2*iDet)
2415             trklA = 0x0;
2416         }
2417         else {
2418           trklNext = trklB;
2419           trklIndexB++;
2420           trklB = trklIndexB < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
2421           if (trklB && trklB->GetHCId() != 2*iDet + 1)
2422             trklB = 0x0;
2423         }
2424       }
2425       if (trklNext) {
2426         sortedTracklets.Add(trklNext);
2427
2428       }
2429     }
2430
2431     // updating tracklet indices as in output
2432     if (sortedTracklets.GetEntries() != trklIndex) {
2433       indices[2*iDet + 0] = trklIndex;
2434       indices[2*iDet + 1] = sortedTracklets.GetEntries();
2435     } else {
2436       indices[2*iDet + 0] = indices[2*iDet + 1] = -1;
2437     }
2438   }
2439 }
2440
2441 void AliTRDrawStream::AssignTracklets(AliESDTrdTrack *trdTrack, Int_t *trackletIndex, Int_t refIndex[6])
2442 {
2443   UInt_t mask  = trdTrack->GetLayerMask();
2444   UInt_t stack = trdTrack->GetStack();
2445
2446   for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
2447     refIndex[iLayer] = -1;
2448
2449     if (mask & (1 << iLayer)) {
2450
2451       Int_t det = trdTrack->GetSector()*30 + stack*6 + iLayer;
2452       Int_t idx = trdTrack->GetTrackletIndex(iLayer);
2453
2454       if ((det < 0) || (det > 539)) {
2455         AliErrorClass(Form("Invalid detector no. from track: %i", 2*det));
2456         continue;
2457       }
2458       if (trackletIndex[2*det] >= 0) {
2459         if ((trackletIndex[2*det] + idx > -1) &&
2460             (trackletIndex[2*det] + idx < trackletIndex[2*det+1])) {
2461           refIndex[iLayer] = trackletIndex[2*det] + idx;
2462         } else {
2463           AliErrorClass(Form("Requested tracklet index %i out of range", idx));
2464         }
2465       } else {
2466         AliErrorClass(Form("Non-existing tracklets requested in det %i", det));
2467       }
2468     }
2469   }
2470 }