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