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