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