]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TRD/AliTRDrawStream.cxx
9ada058dabcc1eecdfb5a7e68341e780484631e7
[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                                       //
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 "AliTreeLoader.h"
41
42 #include "AliTRDrawStream.h"
43
44 // temporary
45 #include "AliRunLoader.h"
46
47 ClassImp(AliTRDrawStream)
48
49 // some static information 
50 const Int_t AliTRDrawStream::fgkMcmOrder[] = {12, 13, 14, 15, 
51                                               8, 9, 10, 11, 
52                                               4, 5, 6, 7, 
53                                               0, 1, 2, 3};
54 const Int_t  AliTRDrawStream::fgkRobOrder [] = {0, 1, 2, 3};
55 const Int_t  AliTRDrawStream::fgkNlinks = 12;
56 const Int_t  AliTRDrawStream::fgkNstacks = 5;
57 const UInt_t AliTRDrawStream::fgkDataEndmarker     = 0x00000000;
58 const UInt_t AliTRDrawStream::fgkTrackletEndmarker = 0x10001000;
59
60 const char* AliTRDrawStream::fgErrorMessages[] = {
61   "Unknown error",
62   "Link monitor active",
63   "Pretrigger counter mismatch",
64   "not a TRD equipment (1024-1041)",
65   "Invalid Stack header",
66   "Invalid detector number",
67   "No digits could be retrieved from the digitsmanager",
68   "HC header mismatch", 
69   "HC check bits wrong",
70   "Unexpected position in readout stream",
71   "Invalid testpattern mode",
72   "Testpattern mismatch",
73   "Number of timebins changed",
74   "ADC mask inconsistent", 
75   "ADC check bits invalid", 
76   "Missing ADC data",
77   "Missing expected ADC channels",
78   "Missing MCM headers"
79 };
80
81 const Int_t AliTRDrawStream::fgErrorDebugLevel[] = {
82   0,
83   0,
84   2, 
85   1, 
86   0, 
87   1, 
88   1, 
89   1,
90   1, 
91   2,
92   1,
93   1,
94   1,
95   1, 
96   2, 
97   1, 
98   1, 
99   1
100 };
101
102 AliTRDrawStream::ErrorBehav_t AliTRDrawStream::fgErrorBehav[] = {
103   AliTRDrawStream::kTolerate,
104   AliTRDrawStream::kDiscardHC,
105   AliTRDrawStream::kTolerate,
106   AliTRDrawStream::kAbort,
107   AliTRDrawStream::kAbort,
108   AliTRDrawStream::kAbort,
109   AliTRDrawStream::kAbort,
110   AliTRDrawStream::kDiscardHC,
111   AliTRDrawStream::kDiscardHC,
112   AliTRDrawStream::kTolerate,
113   AliTRDrawStream::kTolerate,
114   AliTRDrawStream::kTolerate,
115   AliTRDrawStream::kTolerate,
116   AliTRDrawStream::kTolerate,
117   AliTRDrawStream::kTolerate,
118   AliTRDrawStream::kTolerate,
119   AliTRDrawStream::kTolerate,
120   AliTRDrawStream::kTolerate
121 };
122
123 AliTRDrawStream::AliTRDrawStream(AliRawReader *rawReader) :
124   fStats(), 
125   fStoreError(&AliTRDrawStream::StoreErrorTree),
126   fRawReader(rawReader),
127   fDigitsManager(0x0),
128   fDigitsParam(0x0),
129   fErrors(0x0),
130   fLastError(),
131   fErrorFlags(0),
132   fPayloadStart(0x0),
133   fPayloadCurr(0x0),
134   fPayloadSize(0),
135   fNtimebins(-1),
136   fLastEvId(-1),
137   fCurrSlot(-1),
138   fCurrLink(-1),
139   fCurrRobPos(-1),
140   fCurrMcmPos(-1),
141   fCurrEquipmentId(0),
142   fCurrSmuIndexHeaderSize(0),
143   fCurrSmuIndexHeaderVersion(0),
144   fCurrTrackEnable(0),
145   fCurrTrackletEnable(0),
146   fCurrStackMask(0),
147   fCurrStackIndexWord(0x0),
148   fCurrStackHeaderSize(0x0),
149   fCurrStackHeaderVersion(0x0),
150   fCurrLinkMask(0x0),
151   fCurrCleanCheckout(0x0),
152   fCurrBoardId(0x0),
153   fCurrHwRev(0x0),
154   fCurrLinkMonitorFlags(0x0),
155   fCurrLinkDataTypeFlags(0x0),
156   fCurrLinkDebugFlags(0x0),
157   fCurrSpecial(-1),
158   fCurrMajor(-1),
159   fCurrMinor(-1),
160   fCurrAddHcWords(-1),
161   fCurrSm(-1),
162   fCurrStack(-1),
163   fCurrLayer(-1),
164   fCurrSide(-1),
165   fCurrHC(-1),
166   fCurrCheck(-1),
167   fCurrNtimebins(-1),
168   fCurrBC(-1),
169   fCurrPtrgCnt(-1),
170   fCurrPtrgPhase(-1),
171   fNDumpMCMs(0),
172   fTrackletArray(0x0),
173   fAdcArray(0x0),
174   fSignalIndex(0x0),
175   fTrackletTree(0x0)
176 {
177   // default constructor
178
179   fCurrStackIndexWord     = new UInt_t[fgkNstacks];      
180   fCurrStackHeaderSize    = new UInt_t[fgkNstacks];      
181   fCurrStackHeaderVersion = new UInt_t[fgkNstacks];
182   fCurrLinkMask           = new UInt_t[fgkNstacks];              
183   fCurrCleanCheckout      = new UInt_t[fgkNstacks];      
184   fCurrBoardId            = new UInt_t[fgkNstacks];              
185   fCurrHwRev              = new UInt_t[fgkNstacks];             
186   fCurrLinkMonitorFlags   = new UInt_t[fgkNstacks * fgkNlinks];
187   fCurrLinkDataTypeFlags  = new UInt_t[fgkNstacks * fgkNlinks];
188   fCurrLinkDebugFlags     = new UInt_t[fgkNstacks * fgkNlinks];
189
190   // preparing TClonesArray
191   fTrackletArray = new TClonesArray("AliTRDtrackletWord", 256);
192
193   // setting up the error tree
194   fErrors = new TTree("errorStats", "Error statistics");
195   fErrors->SetDirectory(0x0);
196   fErrors->Branch("error", &fLastError, "sector/I:stack:link:error:rob:mcm");
197   fErrors->SetCircular(1000);
198 }
199
200 AliTRDrawStream::~AliTRDrawStream()
201 {
202   // destructor
203
204   delete fErrors;
205
206   delete [] fCurrStackIndexWord;
207   delete [] fCurrStackHeaderSize;
208   delete [] fCurrStackHeaderVersion;
209   delete [] fCurrLinkMask;
210   delete [] fCurrCleanCheckout;
211   delete [] fCurrBoardId;
212   delete [] fCurrHwRev;
213   delete [] fCurrLinkMonitorFlags;
214   delete [] fCurrLinkDataTypeFlags;
215   delete [] fCurrLinkDebugFlags;
216 }
217
218 Bool_t AliTRDrawStream::ReadEvent(TTree *trackletTree)
219 {
220   // read the current event from the raw reader and fill it to the digits manager
221
222   if (!fRawReader) {
223     AliError("No raw reader available");
224     return kFALSE;
225   }
226
227   // tracklet output
228   ConnectTracklets(trackletTree);
229
230   // some preparations
231   fDigitsParam = 0x0;
232
233   // loop over all DDLs
234   // data starts with GTU payload, i.e. SMU index word
235   UChar_t *buffer = 0x0;
236
237   while (fRawReader->ReadNextData(buffer)) {
238
239     fCurrEquipmentId = fRawReader->GetEquipmentId();
240     AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
241
242     if (fCurrEquipmentId < 1024 || fCurrEquipmentId > 1041) {
243       EquipmentError(kNonTrdEq, "Skipping");
244       continue;
245     }
246
247     // setting the pointer to data and current reading position
248     fPayloadCurr = fPayloadStart = (UInt_t*) (buffer);
249     fPayloadSize = fRawReader->GetDataSize() / sizeof(UInt_t);
250     fStats.fStatsSector[fCurrEquipmentId - 1024].fBytes = fRawReader->GetDataSize();
251     AliDebug(2, Form("Read buffer of size: %i", fRawReader->GetDataSize()));
252
253     // read SMU index header
254     if (ReadSmHeader() < 0) {
255       AliError(Form("Reading SMU header failed, skipping this DDL %i", fCurrEquipmentId));
256       continue;
257     }
258
259     // read stack index header
260     for (Int_t iStack = 0; iStack < 5; iStack++) {
261       if ((fCurrStackMask & (1 << iStack)) != 0) 
262         ReadStackIndexHeader(iStack);
263     }
264
265     for (Int_t iStack = 0; iStack < 5; iStack++) {
266       fCurrSlot = iStack;
267       if ((fCurrStackMask & (1 << fCurrSlot)) == 0) 
268         continue;
269
270       AliDebug(2, Form("Stack %i, Link mask: 0x%02x", fCurrSlot, fCurrLinkMask[fCurrSlot]));
271       for (Int_t iLink = 0; iLink < 12; iLink++) {
272         fCurrLink = iLink;
273         fCurrHC   = fCurrSm * 60 + fCurrSlot * 12 + iLink;
274         if ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) == 0)
275           continue;
276         
277         fErrorFlags = 0;
278         // check for link monitor error flag
279         if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0)
280           LinkError(kLinkMonitor);
281
282         // read the data from one HC
283         ReadLinkData();
284
285         // read all data endmarkers
286         SeekNextLink();
287       }
288     }
289   }
290   return kTRUE;
291 }
292
293
294 Bool_t AliTRDrawStream::NextDDL()
295 {
296   // continue reading with the next equipment
297
298   if (!fRawReader)
299     return kFALSE;
300
301   fCurrEquipmentId = 0;
302   fCurrSlot = 0;
303   fCurrLink = 0;
304
305   UChar_t *buffer = 0x0;
306
307   while (fRawReader->ReadNextData(buffer)) {
308
309     fCurrEquipmentId = fRawReader->GetEquipmentId();
310     AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
311     
312     if (fCurrEquipmentId < 1024 || fCurrEquipmentId > 1041) {
313       EquipmentError(kNonTrdEq, "Skipping");
314       continue;
315     }
316
317     // setting the pointer to data and current reading position
318     fPayloadCurr = fPayloadStart = (UInt_t*) (buffer);
319     fPayloadSize = fRawReader->GetDataSize() / sizeof(UInt_t);
320     AliDebug(2, Form("Read buffer of size: %i", fRawReader->GetDataSize()));
321
322     // read SMU index header
323     if (ReadSmHeader() < 0) {
324       AliError(Form("Reading SMU header failed, skipping this DDL %i", fCurrEquipmentId));
325       continue;
326     }
327     
328     // read stack index header
329     for (Int_t iStack = 0; iStack < 5; iStack++) {
330       if ((fCurrStackMask & (1 << iStack)) != 0) {
331         ReadStackIndexHeader(iStack);
332       }
333     }
334     return kTRUE;
335   }
336
337   return kFALSE;
338 }
339
340
341 Int_t AliTRDrawStream::NextChamber(AliTRDdigitsManager *digMgr, UInt_t ** /* trackletContainer */, UShort_t ** /* errorContainer */)
342 {
343   // read the data for the next chamber
344   // in case you only want to read the data of a single chamber
345   // to read all data ReadEvent(...) is recommended
346
347   fDigitsManager = digMgr; 
348   fDigitsParam   = 0x0;
349
350   fErrorFlags = 0;
351
352   // tracklet output preparation
353   TTree *trklTree = 0x0;
354   AliRunLoader *rl = AliRunLoader::Instance();
355   AliLoader* trdLoader = rl ? rl->GetLoader("TRDLoader") : NULL;
356   AliDataLoader *trklLoader = trdLoader ? trdLoader->GetDataLoader("tracklets") : NULL;
357   if (trklLoader) {
358     AliTreeLoader *trklTreeLoader = (AliTreeLoader*) trklLoader->GetBaseLoader("tracklets-raw");
359     if (trklTreeLoader) 
360       trklTree = trklTreeLoader->Tree();
361     else 
362       trklTree = trklLoader->Tree();
363   }
364
365   if (fTrackletTree != trklTree)
366     ConnectTracklets(trklTree);
367
368   if (!fRawReader) {
369     AliError("No raw reader available");
370     return -1;
371   }
372
373   if (fCurrSlot < 0 || fCurrSlot >= 5) {
374     if (!NextDDL()) {
375       fCurrSlot = -1;
376       return -1;
377     }
378   }
379
380   AliDebug(2, Form("Stack %i, Link %i, mask: 0x%02x", fCurrSlot, fCurrLink, fCurrLinkMask[fCurrSlot]));
381   fCurrHC   = (fCurrEquipmentId - 1024) * 60 + fCurrSlot * 12 + fCurrLink;
382
383   if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0)
384     LinkError(kLinkMonitor);
385
386   // read the data from one HC
387   ReadLinkData();
388   
389   // read all data endmarkers
390   SeekNextLink();
391
392   if (fCurrLink % 2 == 0) {
393     // if we just read the A-side HC then also check the B-side
394     fCurrLink++;
395     fCurrHC++;
396     if (fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) {
397       ReadLinkData();
398       SeekNextLink();
399     }
400   }
401
402   //??? to check 
403   do {
404     fCurrLink++; 
405     if (fCurrLink > 11) {
406       fCurrLink = 0;
407       fCurrSlot++;
408     }
409   } while ((fCurrSlot < 5) && 
410            (((fCurrStackMask & (1 << fCurrSlot)) == 0) || 
411             ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0));
412
413   return (fCurrSm * 30 + fCurrStack * 6 + fCurrLayer);
414 }
415
416
417 Int_t AliTRDrawStream::ReadSmHeader()
418 {
419   // read the SMU index header at the current reading position 
420   // and store the information in the corresponding variables
421
422   if (fPayloadCurr - fPayloadStart >= fPayloadSize - 1) {
423     EquipmentError(kUnknown, "SM Header incomplete");
424     return -1;
425   }
426
427   fCurrSmuIndexHeaderSize     = ((*fPayloadCurr) >> 16) & 0xffff;
428   fCurrSmuIndexHeaderVersion  = ((*fPayloadCurr) >> 12) &    0xf;
429   fCurrTrackEnable            = ((*fPayloadCurr) >>  6) &    0x1;
430   fCurrTrackletEnable         = ((*fPayloadCurr) >>  5) &    0x1;
431   fCurrStackMask              = ((*fPayloadCurr)      ) &   0x1f;
432
433   AliDebug(5, Form("SMU header: size: %i, version: %i, track enable: %i, tracklet enable: %i, stack mask: %2x",
434                    fCurrSmuIndexHeaderSize, 
435                    fCurrSmuIndexHeaderVersion, 
436                    fCurrTrackEnable, 
437                    fCurrTrackletEnable,
438                    fCurrStackMask));
439   
440   fPayloadCurr += fCurrSmuIndexHeaderSize + 1;
441
442   return fCurrSmuIndexHeaderSize + 1;
443 }
444
445 Int_t AliTRDrawStream::ReadStackIndexHeader(Int_t stack)
446 {
447   // read the stack index header 
448   // and store the information in the corresponding variables
449
450   fCurrStackIndexWord[stack]     = *fPayloadCurr;
451   fCurrStackHeaderSize[stack]    = (((*fPayloadCurr) >> 16) & 0xffff) + 1;
452   fCurrStackHeaderVersion[stack] = ((*fPayloadCurr) >> 12) & 0xf;
453   fCurrLinkMask[stack]           = (*fPayloadCurr) & 0xfff;
454
455   if (fPayloadCurr - fPayloadStart >= fPayloadSize - (Int_t) fCurrStackHeaderSize[stack]) {
456     StackError(kStackHeaderInvalid, "Stack index header aborted");
457     return -1;
458   }
459
460   switch (fCurrStackHeaderVersion[stack]) {
461   case 0xa: 
462     if (fCurrStackHeaderSize[stack] < 8) {
463       StackError(kStackHeaderInvalid, "Stack header smaller than expected!");
464       return -1;
465     }
466     
467     fCurrCleanCheckout[stack] = fPayloadCurr[1] & 0x1;
468     fCurrBoardId[stack]       = (fPayloadCurr[1] >> 8) & 0xff;
469     fCurrHwRev[stack]         = (fPayloadCurr[1] >> 16) & 0xffff;
470     
471     for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
472       // A side
473       fCurrLinkMonitorFlags  [stack*fgkNlinks + iLayer*2]      = fPayloadCurr[iLayer+2] & 0xf;
474       fCurrLinkDataTypeFlags [stack*fgkNlinks + iLayer*2]      = (fPayloadCurr[iLayer+2] >> 4) & 0x3;
475       fCurrLinkDebugFlags    [stack*fgkNlinks + iLayer*2]      = (fPayloadCurr[iLayer+2] >> 12) & 0xf;
476       // B side
477       fCurrLinkMonitorFlags  [stack*fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 16) & 0xf;
478       fCurrLinkDataTypeFlags [stack*fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 20) & 0x3;
479       fCurrLinkDebugFlags    [stack*fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 28) & 0xf;
480     }
481     break;
482     
483   default:
484     StackError(kStackHeaderInvalid, "Invalid Stack Index Header version %x", fCurrStackHeaderVersion[stack]);
485   }
486   
487   fPayloadCurr += fCurrStackHeaderSize[stack];
488
489   return fCurrStackHeaderSize[stack];
490 }
491
492 Int_t AliTRDrawStream::ReadLinkData()
493 {
494   // read the data in one link (one HC) until the data endmarker is reached
495   // returns the number of words read!
496
497   Int_t count = 0;
498   UInt_t* startPosLink = fPayloadCurr;
499
500 //  printf("----- HC: %i -----\n", fCurrHC);
501 //  for (Int_t i = 0; i < 3; i++) {
502 //    printf("0x%08x 0x%08x 0x%08x 0x%08x\n", 
503 //         fPayloadCurr[i*4+0], fPayloadCurr[i*4+1], fPayloadCurr[i*4+2], fPayloadCurr[i*4+3]);
504 //  }
505
506   if (fErrorFlags & kDiscardHC)
507     return count;
508
509   count += ReadTracklets();
510   if (fErrorFlags & kDiscardHC)
511     return count;
512
513   count += ReadHcHeader();
514   if (fErrorFlags & kDiscardHC)
515     return count;
516
517   Int_t det = fCurrSm * 30 + fCurrStack * 6 + fCurrLayer;
518
519   if (det > -1 && det < 540) {
520     
521     if ((fAdcArray = fDigitsManager->GetDigits(det))) {
522       //fAdcArray->Expand();
523       if (fAdcArray->GetNtime() != fCurrNtimebins)
524         fAdcArray->Allocate(16, 144, fCurrNtimebins);
525     }
526     else {
527       LinkError(kNoDigits);
528     }
529     
530     if (!fDigitsParam) {
531       fDigitsParam = fDigitsManager->GetDigitsParam();
532     }
533     if (fDigitsParam) {
534       fDigitsParam->SetPretriggerPhase(det, fCurrPtrgPhase);
535       fDigitsParam->SetNTimeBins(det, fCurrNtimebins);
536       fDigitsParam->SetADCbaseline(det, 10);
537     }
538     
539     if (fDigitsManager->UsesDictionaries()) {
540       fDigitsManager->GetDictionary(det, 0)->Reset();
541       fDigitsManager->GetDictionary(det, 1)->Reset();
542       fDigitsManager->GetDictionary(det, 2)->Reset();
543     }
544
545     if ((fSignalIndex = fDigitsManager->GetIndexes(det))) {
546       fSignalIndex->SetSM(fCurrSm);
547       fSignalIndex->SetStack(fCurrStack);
548       fSignalIndex->SetLayer(fCurrLayer);
549       fSignalIndex->SetDetNumber(det);
550       if (!fSignalIndex->IsAllocated())
551         fSignalIndex->Allocate(16, 144, fCurrNtimebins);
552     }
553     
554     // ----- check which kind of data -----
555     if (fCurrMajor & 0x40) {
556       if ((fCurrMajor & 0x7) == 0x7) {
557         AliDebug(1, "This is a config event");
558         UInt_t *startPos = fPayloadCurr;
559         while (fPayloadCurr - fPayloadStart < fPayloadSize &&
560                *fPayloadCurr != fgkDataEndmarker)
561           fPayloadCurr++;
562         count += fPayloadCurr - startPos;
563         
564         // feeding TRAP config
565         AliTRDtrapConfig *trapcfg = AliTRDtrapConfig::Instance();
566         trapcfg->ReadPackedConfig(fCurrHC, startPos, fPayloadCurr - startPos);
567       }
568       else {
569         Int_t tpmode = fCurrMajor & 0x7;
570         AliDebug(1, Form("Checking testpattern (mode %i) data", tpmode));
571         ReadTPData(tpmode);
572       }
573     }
574     else if (fCurrMajor & 0x20) {
575       AliDebug(1, "This is a zs event");
576       count += ReadZSData();
577     }
578     else {
579       AliDebug(1, "This is a nozs event");
580       count += ReadNonZSData();
581     }
582   }
583   else {
584     LinkError(kInvalidDetector, "%i", det);
585     while (fPayloadCurr - fPayloadStart < fPayloadSize &&
586            *fPayloadCurr != fgkDataEndmarker)
587       fPayloadCurr++;
588   }
589   
590   fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytes     += (fPayloadCurr - startPosLink) * sizeof(UInt_t);
591   fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytesRead += count * sizeof(UInt_t);
592   fStats.fStatsSector[fCurrSm].fBytesRead                      += count * sizeof(UInt_t);
593   fStats.fBytesRead                                            += count * sizeof(UInt_t);
594
595   return count;
596 }
597
598 Int_t AliTRDrawStream::ReadTracklets()
599 {
600   // read the tracklets from one HC
601
602   fTrackletArray->Clear();
603
604   UInt_t *start = fPayloadCurr;
605   while (*(fPayloadCurr) != fgkTrackletEndmarker && 
606          fPayloadCurr - fPayloadStart < fPayloadSize) {
607
608     new ((*fTrackletArray)[fTrackletArray->GetEntriesFast()]) AliTRDtrackletWord(*(fPayloadCurr));
609
610     fPayloadCurr++;
611   }
612
613   if (fTrackletArray->GetEntriesFast() > 0) {
614     AliDebug(1, Form("Found %i tracklets in %i %i %i (ev. %i)", fTrackletArray->GetEntriesFast(), 
615                      fCurrSm, fCurrSlot, fCurrLink, fRawReader->GetEventIndex()));
616     fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNTracklets += fTrackletArray->GetEntriesFast();
617     fStats.fStatsSector[fCurrSm].fNTracklets                      += fTrackletArray->GetEntriesFast();
618     if (fTrackletTree)
619       fTrackletTree->Fill();
620   }
621
622   // loop over remaining tracklet endmarkers
623   while ((*(fPayloadCurr) == fgkTrackletEndmarker && 
624           fPayloadCurr - fPayloadStart < fPayloadSize)) 
625     fPayloadCurr++;
626   
627   return fPayloadCurr - start;
628 }
629
630 Int_t AliTRDrawStream::ReadHcHeader()
631 {
632   // read and parse the HC header of one HC
633   // and store the information in the corresponding variables
634
635   UInt_t *start = fPayloadCurr;
636   // check not to be at the data endmarker
637   if (*fPayloadCurr == fgkDataEndmarker)
638     return 0;
639
640   fCurrSpecial    = (*fPayloadCurr >> 31) & 0x1;
641   fCurrMajor      = (*fPayloadCurr >> 24) & 0x7f;
642   fCurrMinor      = (*fPayloadCurr >> 17) & 0x7f;
643   fCurrAddHcWords = (*fPayloadCurr >> 14) & 0x7;
644   fCurrSm         = (*fPayloadCurr >> 9) & 0x1f;
645   fCurrLayer      = (*fPayloadCurr >> 6) & 0x7;
646   fCurrStack      = (*fPayloadCurr >> 3) & 0x7;
647   fCurrSide       = (*fPayloadCurr >> 2) & 0x1;
648   fCurrCheck      = (*fPayloadCurr) & 0x3;
649
650   if (fCurrSm != (((Int_t) fCurrEquipmentId) - 1024) || 
651       fCurrStack != fCurrSlot || 
652       fCurrLayer != fCurrLink / 2 || 
653       fCurrSide != fCurrLink % 2) {
654     LinkError(kHCmismatch,
655               "HC: %i, %i, %i, %i\n 0x%08x 0x%08x 0x%08x 0x%08x", 
656               fCurrSm, fCurrStack, fCurrLayer, fCurrSide,
657               fPayloadCurr[0], fPayloadCurr[1], fPayloadCurr[2], fPayloadCurr[3]);;
658   }
659   if (fCurrCheck != 0x1) {
660     LinkError(kHCcheckFailed);
661   }
662   
663   if (fCurrAddHcWords > 0) {
664     fCurrNtimebins = (fPayloadCurr[1] >> 26) & 0x3f;
665     fCurrBC = (fPayloadCurr[1] >> 10) & 0xffff;
666     fCurrPtrgCnt = (fPayloadCurr[1] >> 6) & 0xf;
667     fCurrPtrgPhase = (fPayloadCurr[1] >> 2) & 0xf;
668   }
669   
670   fPayloadCurr += 1 + fCurrAddHcWords;
671   
672   return (fPayloadCurr - start) / sizeof(UInt_t);
673 }
674
675 Int_t AliTRDrawStream::ReadTPData(Int_t mode)
676 {
677   // testing of testpattern 1 to 3 (hardcoded), 0 missing
678   // evcnt checking missing
679   Int_t cpu = 0;
680   Int_t cpufromchannel[] = {0, 0, 0, 0, 0,  1, 1, 1, 1, 1,  2, 2, 2, 2, 2,  3, 3, 3, 3, 3, 3};
681   Int_t evcnt = 0;
682   Int_t count = 0;
683   Int_t mcmcount = -1;
684   Int_t wordcount = 0;
685   Int_t channelcount = 0;
686   UInt_t expword = 0;
687   UInt_t expadcval = 0;
688   UInt_t diff = 0;
689   Int_t lastmcmpos = -1;
690   Int_t lastrobpos = -1;
691
692   UInt_t* start = fPayloadCurr;
693
694   while (*(fPayloadCurr) != fgkDataEndmarker && 
695          fPayloadCurr - fPayloadStart < fPayloadSize - 1) {
696
697     // ----- Checking MCM Header -----
698     AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
699     mcmcount++;
700     
701     // ----- checking for proper readout order - ROB -----
702     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
703       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
704     }
705     else {
706       ROBError(kPosUnexp);
707     }
708     fCurrRobPos = ROB(*fPayloadCurr);
709     
710     // ----- checking for proper readout order - MCM -----
711     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) >= (lastmcmpos + 1) % 16) {
712       lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
713     }
714     else {
715       MCMError(kPosUnexp);
716     }
717     fCurrMcmPos = MCM(*fPayloadCurr);
718     
719
720     fPayloadCurr++;
721     
722     evcnt = 0x3f & *fPayloadCurr >> 26;
723     cpu = -1;
724     channelcount = 0;
725     while (channelcount < 21) {
726       count = 0;
727       if (cpu != cpufromchannel[channelcount]) {
728         cpu = cpufromchannel[channelcount];
729         expadcval = (1 << 9) | (fCurrRobPos << 6) | (fCurrMcmPos << 2) | cpu;
730         wordcount = 0;
731       }
732       
733       while (count < 10) {
734         if (channelcount % 2 == 0)
735           expword = 0x3;
736         else 
737           expword = 0x2;
738         
739         if (mode == 1) {
740           // ----- TP 1 -----
741           expword |= expadcval << 2;
742           expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
743           expword |= expadcval << 12;
744           expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
745           expword |= expadcval << 22;
746           expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
747         }
748         else if (mode == 2) {
749           // ----- TP 2 ------
750           expword = ((0x3f & evcnt) << 26) | ((fCurrSm + 1) << 21) | ((fCurrLayer + 1) << 18) | 
751             ((fCurrStack + 1) << 15) | 
752             (fCurrRobPos << 12) | (fCurrMcmPos << 8) | (cpu << 6) | (wordcount + 1); 
753         }
754         else if (mode == 3) {
755           // ----- TP 3 -----
756           expword = ((0xfff & evcnt) << 20) | (fCurrSm << 15) | (fCurrLink/2 << 12) | (fCurrStack << 9) | 
757             (fCurrRobPos << 6) | (fCurrMcmPos << 2) | (cpu << 0); 
758         }
759         else {
760           expword = 0;
761           LinkError(kTPmodeInvalid, "Just reading");
762         }
763
764         diff = *fPayloadCurr ^ expword;
765         if (diff != 0) {
766           MCMError(kTPmismatch,
767                    "Seen 0x%08x, expected 0x%08x, diff: 0x%08x (0x%02x)", 
768                    *fPayloadCurr, expword, diff, 0xff & (diff | diff >> 8 | diff >> 16 | diff >> 24));;
769         }
770         fPayloadCurr++;
771         count++;
772         wordcount++;
773       }
774       channelcount++;
775     }
776     // continue with next MCM
777   }
778   return fPayloadCurr - start; 
779 }
780
781
782 Int_t AliTRDrawStream::ReadZSData()
783 {
784   // read the zs data from one link from the current reading position
785   
786   UInt_t *start = fPayloadCurr;
787   
788   Int_t mcmcount = 0;
789   Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
790   Int_t channelcount = 0;
791   Int_t channelcountExp = 0;
792   Int_t channelcountMax = 0;
793   Int_t timebins;
794   Int_t currentTimebin = 0;
795   Int_t adcwc = 0;
796   Int_t evno = -1;
797   Int_t lastmcmpos = -1;
798   Int_t lastrobpos = -1;
799
800   if (fCurrNtimebins != fNtimebins) {
801     if (fNtimebins > 0) 
802       LinkError(kNtimebinsChanged,
803                 "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
804     fNtimebins = fCurrNtimebins;
805   }
806   
807   timebins = fNtimebins;
808   
809   while (*(fPayloadCurr) != fgkDataEndmarker && 
810          fPayloadCurr - fPayloadStart < fPayloadSize) {
811     
812     // ----- Checking MCM Header -----
813     AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
814     UInt_t *startPosMCM = fPayloadCurr;
815     
816     // ----- checking for proper readout order - ROB -----
817     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
818       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
819     }
820     else {
821       ROBError(kPosUnexp);
822     }
823     fCurrRobPos = ROB(*fPayloadCurr);
824     
825     // ----- checking for proper readout order - MCM -----
826     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
827       lastmcmpos = GetMCMReadoutPos(lastmcmpos);
828     }
829     else {
830       MCMError(kPosUnexp);
831     }
832     fCurrMcmPos = MCM(*fPayloadCurr);
833     
834     if (EvNo(*fPayloadCurr) != evno) {
835       if (evno == -1)
836         evno = EvNo(*fPayloadCurr);
837       else {
838         MCMError(kPtrgCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
839       }
840     }
841     Int_t adccoloff = AdcColOffset(*fPayloadCurr);
842     Int_t padcoloff = PadColOffset(*fPayloadCurr);
843     Int_t row = Row(*fPayloadCurr);
844     fPayloadCurr++;
845     
846     // ----- Reading ADC channels -----
847     AliDebug(2, Form("ADC mask: 0x%08x", *fPayloadCurr));
848     
849     // ----- analysing the ADC mask -----
850     channelcount = 0;
851     channelcountExp = GetNActiveChannelsFromMask(*fPayloadCurr);
852     channelcountMax = GetNActiveChannels(*fPayloadCurr);
853     Int_t channelmask = GetActiveChannels(*fPayloadCurr);
854     Int_t channelno = -1;
855     fPayloadCurr++; 
856
857     if (channelcountExp != channelcountMax) {
858       if (channelcountExp > channelcountMax) {
859         Int_t temp = channelcountExp;
860         channelcountExp = channelcountMax;
861         channelcountMax = temp;
862       }
863       while (channelcountExp < channelcountMax && channelcountExp < 21 && 
864              fPayloadCurr - fPayloadStart < fPayloadSize - 10 * channelcountExp - 1) {
865         MCMError(kAdcMaskInconsistent,
866                  "Possible MCM-H: 0x%08x, possible ADC-mask: 0x%08x", 
867                  *(fPayloadCurr + 10 * channelcountExp), 
868                  *(fPayloadCurr + 10 * channelcountExp + 1) );
869         if (!CouldBeMCMhdr( *(fPayloadCurr + 10 * channelcountExp)) && !CouldBeADCmask( *(fPayloadCurr + 10 * channelcountExp + 1))) 
870           channelcountExp++;
871         else {
872           break;
873         }
874       }
875       MCMError(kAdcMaskInconsistent,
876                "Inconsistency in no. of active channels: Counter: %i, Mask: %i, chosen: %i!", 
877                GetNActiveChannels(fPayloadCurr[-1]), GetNActiveChannelsFromMask(fPayloadCurr[-1]), channelcountExp);
878     }
879     AliDebug(2, Form("expecting %i active channels, timebins: %i", channelcountExp, fCurrNtimebins));
880     
881     // ----- reading marked ADC channels -----
882     while (channelcount < channelcountExp && *(fPayloadCurr) != fgkDataEndmarker) {
883       if (channelno < 20)
884         channelno++;
885       while (channelno < 20 && (channelmask & 1 << channelno) == 0)
886         channelno++;
887       
888       if (fCurrNtimebins > 30) {
889         currentTimebin = ((*fPayloadCurr >> 2) & 0x3f);
890         timebins = ((*fPayloadCurr >> 8) & 0xf) * 3;
891       } 
892       else {
893         currentTimebin = 0;
894       }
895       
896       adcwc = 0;
897       AliDebug(2, Form("Now looking %i words", timebins / 3));
898       Int_t adccol = adccoloff - channelno;
899       Int_t padcol = padcoloff - channelno;
900 //      if (adccol < 3 || adccol > 165) 
901 //      AliInfo(Form("writing channel %i of det %3i %i:%2i to adcrow/-col: %i/%i padcol: %i", 
902 //                   channelno, fCurrHC/2, fCurrRobPos, fCurrMcmPos, row, adccol, padcol));
903
904       while (adcwc < timebins / 3 && 
905              *(fPayloadCurr) != fgkDataEndmarker && 
906              fPayloadCurr - fPayloadStart < fPayloadSize) {
907         int check = 0x3 & *fPayloadCurr;
908         if (channelno % 2 != 0) { // odd channel
909           if (check != 0x2 && channelno < 21) {
910             MCMError(kAdcCheckInvalid,
911                      "%i for %2i. ADC word in odd channel %i", 
912                      check, adcwc+1, channelno);
913           }
914         }
915         else {                  // even channel
916           if (check != 0x3 && channelno < 21) {
917             MCMError(kAdcCheckInvalid,
918                      "%i for %2i. ADC word in even channel %i", 
919                      check, adcwc+1, channelno);
920           }
921         }
922         
923         // filling the actual timebin data
924         int tb2 = 0x3ff & *fPayloadCurr >> 22;
925         int tb1 = 0x3ff & *fPayloadCurr >> 12;
926         int tb0 = 0x3ff & *fPayloadCurr >> 2;
927         if (adcwc != 0 || fCurrNtimebins <= 30) 
928           fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
929         else
930           tb0 = -1;
931         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
932         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
933         
934         adcwc++;
935         fPayloadCurr++;
936       }
937       
938       if (adcwc != timebins / 3) 
939         MCMError(kAdcDataAbort);
940       
941       // adding index 
942       if (padcol > 0 && padcol < 144) {
943         fSignalIndex->AddIndexRC(row, padcol);
944       }
945       
946       channelcount++;
947     }
948
949     fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNChannels += channelcount;
950     fStats.fStatsSector[fCurrSm].fNChannels                      += channelcount;
951     if (channelcount != channelcountExp)
952       MCMError(kAdcChannelsMiss);
953     
954     mcmcount++;
955     fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNMCMs++;
956     fStats.fStatsSector[fCurrSm].fNMCMs++;
957
958     if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
959       DumpRaw(Form("Event %i: Det %3i ROB %i MCM %2i", fRawReader->GetEventIndex(), fCurrHC/2, fCurrRobPos, fCurrMcmPos),
960               startPosMCM, fPayloadCurr - startPosMCM);
961     }
962
963     // continue with next MCM
964   }
965
966   // check for missing MCMs (if header suppression is inactive)
967   if (((fCurrMajor & 0x1) == 0) && (mcmcount != mcmcountExp)) {
968     LinkError(kMissMcmHeaders,
969               "No. of MCM headers %i not as expected: %i", 
970               mcmcount, mcmcountExp);
971   }
972
973   return (fPayloadCurr - start);
974 }
975
976 Int_t AliTRDrawStream::ReadNonZSData()
977 {
978   // read the non-zs data from one link from the current reading position
979   
980   UInt_t *start = fPayloadCurr;
981   
982   Int_t mcmcount = 0;
983   Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
984   Int_t channelcount = 0;
985   Int_t channelcountExp = 0;
986   Int_t timebins;
987   Int_t currentTimebin = 0;
988   Int_t adcwc = 0;
989   Int_t evno = -1;
990   Int_t lastmcmpos = -1;
991   Int_t lastrobpos = -1;
992
993   if (fCurrNtimebins != fNtimebins) {
994     if (fNtimebins > 0) 
995       LinkError(kNtimebinsChanged,
996                 "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
997     fNtimebins = fCurrNtimebins;
998   }
999   
1000   timebins = fNtimebins;
1001   
1002   while (*(fPayloadCurr) != fgkDataEndmarker && 
1003          fPayloadCurr - fPayloadStart < fPayloadSize - 2) {
1004     
1005     // ----- Checking MCM Header -----
1006     AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
1007     
1008     // ----- checking for proper readout order - ROB -----
1009     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1010       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1011     }
1012     else {
1013       ROBError(kPosUnexp);
1014     }
1015     fCurrRobPos = ROB(*fPayloadCurr);
1016     
1017     // ----- checking for proper readout order - MCM -----
1018     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) >= (lastmcmpos + 1) % 16) {
1019       lastmcmpos = GetMCMReadoutPos(*fPayloadCurr);
1020     }
1021     else {
1022       MCMError(kPosUnexp);
1023     }
1024     fCurrMcmPos = MCM(*fPayloadCurr);
1025     
1026     if (EvNo(*fPayloadCurr) != evno) {
1027       if (evno == -1)
1028         evno = EvNo(*fPayloadCurr);
1029       else {
1030         MCMError(kPtrgCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
1031       }
1032     }
1033     
1034     channelcount = 0;
1035     channelcountExp = 21;
1036     int channelno = -1;
1037
1038     Int_t adccoloff = AdcColOffset(*fPayloadCurr);
1039     Int_t padcoloff = PadColOffset(*fPayloadCurr);
1040     Int_t row = Row(*fPayloadCurr);
1041
1042     fPayloadCurr++;
1043
1044     // ----- reading marked ADC channels -----
1045     while (channelcount < channelcountExp && 
1046            *(fPayloadCurr) != fgkDataEndmarker) {
1047       if (channelno < 20)
1048         channelno++;
1049       
1050       currentTimebin = 0;
1051       
1052       adcwc = 0;
1053       AliDebug(2, Form("Now looking %i words", timebins / 3));
1054       Int_t adccol = adccoloff - channelno;
1055       Int_t padcol = padcoloff - channelno;
1056       while (adcwc < timebins / 3 && 
1057              *(fPayloadCurr) != fgkDataEndmarker && 
1058              fPayloadCurr - fPayloadStart < fPayloadSize) {
1059         int check = 0x3 & *fPayloadCurr;
1060         if (channelno % 2 != 0) { // odd channel
1061           if (check != 0x2 && channelno < 21) {
1062             MCMError(kAdcCheckInvalid,
1063                      "%i for %2i. ADC word in odd channel %i", 
1064                      check, adcwc+1, channelno);
1065           }
1066         }
1067         else {                  // even channel
1068           if (check != 0x3 && channelno < 21) {
1069             MCMError(kAdcCheckInvalid,
1070                      "%i for %2i. ADC word in even channel %i", 
1071                      check, adcwc+1, channelno);
1072           }
1073         }
1074         
1075         // filling the actual timebin data
1076         int tb2 = 0x3ff & *fPayloadCurr >> 22;
1077         int tb1 = 0x3ff & *fPayloadCurr >> 12;
1078         int tb0 = 0x3ff & *fPayloadCurr >> 2;
1079         if (adcwc != 0 || fCurrNtimebins <= 30) 
1080           fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
1081         else
1082           tb0 = -1;
1083         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
1084         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
1085
1086         adcwc++;
1087         fPayloadCurr++;
1088       }
1089
1090       if (adcwc != timebins / 3) 
1091         MCMError(kAdcDataAbort);
1092       
1093       // adding index 
1094       if (padcol > 0 && padcol < 144) {
1095         fSignalIndex->AddIndexRC(row, padcol);
1096       }
1097
1098       channelcount++;
1099     }
1100
1101     if (channelcount != channelcountExp)
1102       MCMError(kAdcChannelsMiss);
1103     mcmcount++;
1104     // continue with next MCM
1105   }
1106
1107   // check for missing MCMs (if header suppression is inactive)
1108   if (mcmcount != mcmcountExp) {
1109     LinkError(kMissMcmHeaders,
1110               "%i not as expected: %i", mcmcount, mcmcountExp);
1111   }
1112
1113   return (fPayloadCurr - start);
1114 }
1115
1116 Int_t AliTRDrawStream::SeekNextLink()
1117 {
1118   UInt_t *start = fPayloadCurr;
1119
1120   // read until data endmarkers
1121   while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1122          *fPayloadCurr != fgkDataEndmarker)
1123     fPayloadCurr++;
1124
1125   // read all data endmarkers
1126   while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1127          *fPayloadCurr == fgkDataEndmarker)
1128     fPayloadCurr++;
1129
1130   return (fPayloadCurr - start);
1131 }
1132
1133 Bool_t AliTRDrawStream::ConnectTracklets(TTree *trklTree) 
1134 {
1135   fTrackletTree = trklTree;
1136   if (!fTrackletTree) 
1137     return kTRUE;
1138
1139   if (!fTrackletTree->GetBranch("hc")) 
1140     fTrackletTree->Branch("hc", &fCurrHC, "hc/I");
1141   else 
1142     fTrackletTree->SetBranchAddress("hc", &fCurrHC);
1143
1144   if (!fTrackletTree->GetBranch("trkl")) 
1145     fTrackletTree->Branch("trkl", &fTrackletArray);
1146   else 
1147     fTrackletTree->SetBranchAddress("trkl", &fTrackletArray);
1148
1149   return kTRUE;
1150 }
1151
1152
1153 void AliTRDrawStream::EquipmentError(ErrorCode_t err, const char *const msg, ...)
1154
1155   // register error according to error code on equipment level 
1156   // and return the corresponding error message
1157
1158   fLastError.fSector = fCurrEquipmentId - 1024;
1159   fLastError.fStack  = -1;
1160   fLastError.fLink   = -1;
1161   fLastError.fRob    = -1;
1162   fLastError.fMcm    = -1;
1163   fLastError.fError  = err;
1164   (this->*fStoreError)();
1165
1166   va_list ap;
1167   if (fgErrorDebugLevel[err] > 10) 
1168     AliDebug(fgErrorDebugLevel[err],
1169              Form("Event %6i: Eq. %2d - %s : %s", 
1170                   fRawReader->GetEventIndex(), fCurrEquipmentId, fgErrorMessages[err],
1171                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1172   else 
1173     AliError(Form("Event %6i: Eq. %2d - %s : %s", 
1174                   fRawReader->GetEventIndex(), fCurrEquipmentId, fgErrorMessages[err],
1175                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1176   fErrorFlags |= fgErrorBehav[err];
1177 }                                                                               
1178
1179
1180 void AliTRDrawStream::StackError(ErrorCode_t err, const char *const msg, ...)
1181
1182   // register error according to error code on stack level 
1183   // and return the corresponding error message
1184
1185   fLastError.fSector = fCurrEquipmentId - 1024;
1186   fLastError.fStack  = fCurrSlot;
1187   fLastError.fLink   = -1;
1188   fLastError.fRob    = -1;
1189   fLastError.fMcm    = -1;
1190   fLastError.fError  = err;
1191   (this->*fStoreError)();
1192
1193   va_list ap;
1194   if (fgErrorDebugLevel[err] > 0) 
1195     AliDebug(fgErrorDebugLevel[err], 
1196              Form("Event %6i: Eq. %2d S %i - %s : %s", 
1197                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgErrorMessages[err],
1198                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1199   else 
1200     AliError(Form("Event %6i: Eq. %2d S %i - %s : %s", 
1201                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgErrorMessages[err],
1202                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1203   fErrorFlags |= fgErrorBehav[err];
1204
1205
1206
1207 void AliTRDrawStream::LinkError(ErrorCode_t err, const char *const msg, ...)
1208
1209   // register error according to error code on link level 
1210   // and return the corresponding error message
1211
1212   fLastError.fSector = fCurrEquipmentId - 1024;
1213   fLastError.fStack  = fCurrSlot;
1214   fLastError.fLink   = fCurrLink;
1215   fLastError.fRob    = -1;
1216   fLastError.fMcm    = -1;
1217   fLastError.fError  = err;
1218   (this->*fStoreError)();
1219
1220   va_list ap;
1221   if (fgErrorDebugLevel[err] > 0)
1222     AliDebug(fgErrorDebugLevel[err], 
1223              Form("Event %6i: Eq. %2d S %i l %2i - %s : %s", 
1224                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgErrorMessages[err],
1225                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1226   else 
1227     AliError(Form("Event %6i: Eq. %2d S %i l %2i - %s : %s", 
1228                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgErrorMessages[err],
1229                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1230   fErrorFlags |= fgErrorBehav[err];
1231
1232
1233
1234 void AliTRDrawStream::ROBError(ErrorCode_t err, const char *const msg, ...)
1235
1236   // register error according to error code on ROB level 
1237   // and return the corresponding error message
1238
1239   fLastError.fSector = fCurrEquipmentId - 1024;
1240   fLastError.fStack  = fCurrSlot;
1241   fLastError.fLink   = fCurrLink;
1242   fLastError.fRob    = fCurrRobPos;
1243   fLastError.fMcm    = -1;
1244   fLastError.fError  = err;
1245   (this->*fStoreError)();
1246
1247   va_list ap;
1248   if (fgErrorDebugLevel[err] > 0) 
1249     AliDebug(fgErrorDebugLevel[err], 
1250              Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s", 
1251                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgErrorMessages[err],
1252                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1253   else 
1254     AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s", 
1255                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgErrorMessages[err], 
1256                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1257   fErrorFlags |= fgErrorBehav[err];
1258
1259
1260
1261 void AliTRDrawStream::MCMError(ErrorCode_t err, const char *const msg, ...)
1262
1263   // register error according to error code on MCM level 
1264   // and return the corresponding error message
1265
1266   fLastError.fSector = fCurrEquipmentId - 1024;
1267   fLastError.fStack  = fCurrSlot;
1268   fLastError.fLink   = fCurrLink;
1269   fLastError.fRob    = fCurrRobPos;
1270   fLastError.fMcm    = fCurrMcmPos;
1271   fLastError.fError  = err;
1272   (this->*fStoreError)();
1273
1274   va_list ap;
1275   if (fgErrorDebugLevel[err] > 0) 
1276     AliDebug(fgErrorDebugLevel[err], 
1277              Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
1278                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgErrorMessages[err], 
1279                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1280   else 
1281     AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
1282                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgErrorMessages[err], 
1283                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1284   fErrorFlags |= fgErrorBehav[err];
1285 }
1286
1287 const char* AliTRDrawStream::GetErrorMessage(ErrorCode_t errCode)
1288
1289   // return the error message for the given error code
1290
1291   if (errCode > 0 && errCode < kLastErrorCode) 
1292     return fgErrorMessages[errCode];
1293   else 
1294     return ""; 
1295
1296
1297 void AliTRDrawStream::AliTRDrawStats::ClearStats()
1298 {
1299   // clear statistics (includes clearing sector-wise statistics)
1300
1301   fBytesRead = 0;
1302   for (Int_t iSector = 0; iSector < 18; iSector++) {
1303     fStatsSector[iSector].ClearStats();
1304   }
1305
1306 }
1307
1308 void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::ClearStats()
1309 {
1310   // clear statistics (includes clearing HC-wise statistics)
1311
1312   fBytes = 0;
1313   fBytesRead = 0;
1314   fNTracklets = 0;
1315   fNMCMs = 0;
1316   fNChannels = 0;
1317
1318   for (Int_t iHC = 0; iHC < 60; iHC++) {
1319     fStatsHC[iHC].ClearStats();
1320   }
1321 }
1322
1323 void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::AliTRDrawStatsHC::ClearStats()
1324 {
1325   // clear statistics
1326
1327   fBytes = 0;
1328   fBytesRead = 0;
1329   fNTracklets = 0;
1330   fNMCMs = 0;
1331   fNChannels = 0;
1332 }
1333
1334 void AliTRDrawStream::SetDumpMCM(Int_t det, Int_t rob, Int_t mcm, Bool_t dump)
1335
1336   // mark MCM for dumping of raw data
1337
1338   if (dump) {
1339     fDumpMCM[fNDumpMCMs++] = (det << 7) | (rob << 4) | mcm; 
1340   }
1341   else {
1342     Int_t iMCM;
1343     for (iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
1344       if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
1345         fNDumpMCMs--;
1346         break;
1347       }
1348     }
1349     for ( ; iMCM < fNDumpMCMs; iMCM++) {
1350       fDumpMCM[iMCM] = fDumpMCM[iMCM+1];
1351     }
1352   }
1353 }
1354
1355 Bool_t AliTRDrawStream::DumpingMCM(Int_t det, Int_t rob, Int_t mcm) 
1356 {
1357   // check if MCM data should be dumped
1358
1359   for (Int_t iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
1360     if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
1361       return kTRUE;
1362     }
1363   }
1364   return kFALSE;
1365 }
1366
1367 void AliTRDrawStream::DumpRaw(TString title, UInt_t *start, Int_t length)
1368 {
1369   // dump raw data
1370
1371   title += "\n";
1372   Int_t pos = 0;
1373   for ( ; pos+3 < length; pos += 4) {
1374     title += Form("0x%08x 0x%08x 0x%08x 0x%08x\n", 
1375                   start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
1376   }
1377   for ( ; pos < length; pos++) {
1378     title += Form("0x%08x ", start[pos]);
1379   }
1380   AliInfo(title);
1381 }
1382
1383 AliTRDrawStream::AliTRDrawStreamError::AliTRDrawStreamError(Int_t error, Int_t sector, Int_t stack, Int_t link, Int_t rob, Int_t mcm) : 
1384   fError(error),
1385   fSector(sector),
1386   fStack(stack),
1387   fLink(link), 
1388   fRob(rob),
1389   fMcm(mcm)
1390 {
1391   // ctor
1392
1393 }