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