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