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