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