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