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