]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TRD/AliTRDrawStream.cxx
write on-line tracklets and tracks to ESD during reconstruction
[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, on-line tracklets and tracks         //
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 #include "AliLoader.h"
43
44 #include "AliTRDrawStream.h"
45
46 // temporary
47 #include "AliRunLoader.h"
48
49 ClassImp(AliTRDrawStream)
50
51 // some static information
52 Int_t AliTRDrawStream::fgMcmOrder[] = {12, 13, 14, 15,
53                                        8, 9, 10, 11,
54                                        4, 5, 6, 7,
55                                        0, 1, 2, 3};
56 Int_t  AliTRDrawStream::fgRobOrder [] = {0, 1, 2, 3};
57 const Int_t  AliTRDrawStream::fgkNlinks = 12;
58 const Int_t  AliTRDrawStream::fgkNstacks = 5;
59 const Int_t  AliTRDrawStream::fgkNsectors = 18;
60 const Int_t  AliTRDrawStream::fgkNtriggers = 12;
61 const UInt_t AliTRDrawStream::fgkDataEndmarker     = 0x00000000;
62 const UInt_t AliTRDrawStream::fgkTrackletEndmarker = 0x10001000;
63
64 const char* AliTRDrawStream::fgkErrorMessages[] = {
65   "Unknown error",
66   "Link monitor active",
67   "Pretrigger counter mismatch",
68   "not a TRD equipment (1024-1041)",
69   "Invalid Stack header",
70   "Invalid detector number",
71   "No digits could be retrieved from the digitsmanager",
72   "HC header mismatch",
73   "HC check bits wrong",
74   "Unexpected position in readout stream",
75   "Invalid testpattern mode",
76   "Testpattern mismatch",
77   "Number of timebins changed",
78   "ADC mask inconsistent",
79   "ADC check bits invalid",
80   "Missing ADC data",
81   "Missing expected ADC channels",
82   "Missing MCM headers"
83 };
84
85 Int_t AliTRDrawStream::fgErrorDebugLevel[] = {
86   0,
87   0,
88   2,
89   1,
90   0,
91   1,
92   1,
93   1,
94   1,
95   2,
96   1,
97   1,
98   1,
99   1,
100   2,
101   1,
102   1,
103   1
104 };
105
106 AliTRDrawStream::ErrorBehav_t AliTRDrawStream::fgErrorBehav[] = {
107   AliTRDrawStream::kTolerate,
108   AliTRDrawStream::kDiscardHC,
109   AliTRDrawStream::kTolerate,
110   AliTRDrawStream::kAbort,
111   AliTRDrawStream::kAbort,
112   AliTRDrawStream::kAbort,
113   AliTRDrawStream::kAbort,
114   AliTRDrawStream::kDiscardHC,
115   AliTRDrawStream::kDiscardHC,
116   AliTRDrawStream::kTolerate,
117   AliTRDrawStream::kTolerate,
118   AliTRDrawStream::kTolerate,
119   AliTRDrawStream::kTolerate,
120   AliTRDrawStream::kTolerate,
121   AliTRDrawStream::kTolerate,
122   AliTRDrawStream::kTolerate,
123   AliTRDrawStream::kTolerate,
124   AliTRDrawStream::kTolerate
125 };
126
127 AliTRDrawStream::AliTRDrawStream(AliRawReader *rawReader) :
128   fStats(),
129   fStoreError(&AliTRDrawStream::ForgetError),
130   fRawReader(rawReader),
131   fDigitsManager(0x0),
132   fDigitsParam(0x0),
133   fErrors(0x0),
134   fLastError(),
135   fErrorFlags(0),
136   fPayloadStart(0x0),
137   fPayloadCurr(0x0),
138   fPayloadSize(0),
139   fNtimebins(-1),
140   fLastEvId(-1),
141   fCurrSlot(-1),
142   fCurrLink(-1),
143   fCurrRobPos(-1),
144   fCurrMcmPos(-1),
145   fCurrEquipmentId(0),
146   fCurrSmHeaderSize(0),
147   fCurrSmHeaderVersion(0),
148   fCurrTrailerReadout(0),
149   fCurrTrgHeaderAvail(0),
150   fCurrTrgHeaderReadout(0),
151   fCurrTrkHeaderAvail(0),
152   fCurrEvType(0),
153   fCurrTriggerEnable(0),
154   fCurrTriggerFired(0),
155   fCurrTrackEnable(0),
156   fCurrTrackletEnable(0),
157   fCurrStackMask(0),
158   fCurrTrkHeaderIndexWord(0x0),
159   fCurrTrkHeaderSize(0x0),
160   fCurrTrgHeaderIndexWord(0x0),
161   fCurrTrgHeaderSize(0x0),
162   fCurrStackIndexWord(0x0),
163   fCurrStackHeaderSize(0x0),
164   fCurrStackHeaderVersion(0x0),
165   fCurrLinkMask(0x0),
166   fCurrCleanCheckout(0x0),
167   fCurrBoardId(0x0),
168   fCurrHwRev(-1),
169   fCurrHwRevTMU(0x0),
170   fCurrLinkMonitorFlags(0x0),
171   fCurrLinkDataTypeFlags(0x0),
172   fCurrLinkDebugFlags(0x0),
173   fCurrSpecial(-1),
174   fCurrMajor(-1),
175   fCurrMinor(-1),
176   fCurrAddHcWords(-1),
177   fCurrSm(-1),
178   fCurrStack(-1),
179   fCurrLayer(-1),
180   fCurrSide(-1),
181   fCurrHC(-1),
182   fCurrCheck(-1),
183   fCurrNtimebins(-1),
184   fCurrBC(-1),
185   fCurrPtrgCnt(-1),
186   fCurrPtrgPhase(-1),
187   fNDumpMCMs(0),
188   fTrackletArray(0x0),
189   fAdcArray(0x0),
190   fSignalIndex(0x0),
191   fTrackletTree(0x0),
192   fTracklets(0x0),
193   fTracks(0x0),
194   fMarkers(0x0)
195 {
196   // default constructor
197
198   fCurrTrkHeaderIndexWord = new UInt_t[fgkNstacks];
199   fCurrTrkHeaderSize      = new UInt_t[fgkNstacks];
200   fCurrTrgHeaderIndexWord = new UInt_t[fgkNtriggers];
201   fCurrTrgHeaderSize      = new UInt_t[fgkNtriggers];
202   fCurrStackIndexWord     = new UInt_t[fgkNstacks];
203   fCurrStackHeaderSize    = new UInt_t[fgkNstacks];
204   fCurrStackHeaderVersion = new UInt_t[fgkNstacks];
205   fCurrLinkMask           = new UInt_t[fgkNstacks];
206   fCurrCleanCheckout      = new UInt_t[fgkNstacks];
207   fCurrBoardId            = new UInt_t[fgkNstacks];
208   fCurrHwRevTMU           = new UInt_t[fgkNstacks];
209   fCurrLinkMonitorFlags   = new UInt_t[fgkNstacks * fgkNlinks];
210   fCurrLinkDataTypeFlags  = new UInt_t[fgkNstacks * fgkNlinks];
211   fCurrLinkDebugFlags     = new UInt_t[fgkNstacks * fgkNlinks];
212   for (Int_t i = 0; i < 100; i++)
213     fDumpMCM[i] = 0;
214
215   // preparing TClonesArray
216   fTrackletArray = new TClonesArray("AliTRDtrackletWord", 256);
217
218   // setting up the error tree
219   fErrors = new TTree("errorStats", "Error statistics");
220   fErrors->SetDirectory(0x0);
221   fErrors->Branch("error", &fLastError);
222   fErrors->SetCircular(1000);
223   for (Int_t i = 0; i < 100; i++) {
224     fErrorBuffer[i] = 0;
225   }
226
227 }
228
229 AliTRDrawStream::~AliTRDrawStream()
230 {
231   // destructor
232
233   delete fErrors;
234
235   delete [] fCurrTrkHeaderIndexWord;
236   delete [] fCurrTrkHeaderSize;
237   delete [] fCurrTrgHeaderIndexWord;
238   delete [] fCurrTrgHeaderSize;
239   delete [] fCurrStackIndexWord;
240   delete [] fCurrStackHeaderSize;
241   delete [] fCurrStackHeaderVersion;
242   delete [] fCurrLinkMask;
243   delete [] fCurrCleanCheckout;
244   delete [] fCurrBoardId;
245   delete [] fCurrHwRevTMU;
246   delete [] fCurrLinkMonitorFlags;
247   delete [] fCurrLinkDataTypeFlags;
248   delete [] fCurrLinkDebugFlags;
249 }
250
251 Bool_t AliTRDrawStream::ReadEvent(TTree *trackletTree)
252 {
253   // read the current event from the raw reader and fill it to the digits manager
254
255   if (!fRawReader) {
256     AliError("No raw reader available");
257     return kFALSE;
258   }
259
260   // tracklet output
261   ConnectTracklets(trackletTree);
262
263   // some preparations
264   fDigitsParam = 0x0;
265
266   // loop over all DDLs
267   // data starts with GTU payload, i.e. SM index word
268   UChar_t *buffer = 0x0;
269
270   while (fRawReader->ReadNextData(buffer)) {
271
272     fCurrEquipmentId = fRawReader->GetEquipmentId();
273     AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
274
275     if (fCurrEquipmentId < kDDLOffset || fCurrEquipmentId > kDDLMax) {
276       EquipmentError(kNonTrdEq, "Skipping");
277       continue;
278     }
279
280     if (fMarkers)
281       new ((*fMarkers)[fMarkers->GetEntriesFast()])
282         AliTRDrawStreamError(-kSecactive, fCurrEquipmentId - kDDLOffset);
283
284     ReadGTUHeaders((UInt_t*) buffer);
285
286     if (fCurrTrailerReadout)
287       ReadGTUTrailer();
288
289     // loop over all active links
290     AliDebug(2, Form("Stack mask 0x%02x", fCurrStackMask));
291     for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
292       fCurrSlot = iStack;
293       if ((fCurrStackMask & (1 << fCurrSlot)) == 0)
294         continue;
295
296       AliDebug(2, Form("Stack %i, Link mask: 0x%02x", fCurrSlot, fCurrLinkMask[fCurrSlot]));
297       for (Int_t iLink = 0; iLink < fgkNlinks; iLink++) {
298         fCurrLink = iLink;
299         fCurrHC   = (fCurrEquipmentId - kDDLOffset) * fgkNstacks * fgkNlinks +
300           fCurrSlot * fgkNlinks + iLink;
301         if ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) == 0)
302           continue;
303
304         fErrorFlags = 0;
305         // check for link monitor error flag
306         if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0)
307           LinkError(kLinkMonitor);
308         else
309           // read the data from one HC
310           ReadLinkData();
311
312         // read all data endmarkers
313         SeekNextLink();
314       }
315     }
316   }
317
318   return kTRUE;
319 }
320
321
322 Bool_t AliTRDrawStream::NextDDL()
323 {
324   // continue reading with the next equipment
325
326   if (!fRawReader)
327     return kFALSE;
328
329   fCurrEquipmentId = 0;
330   fCurrSlot = 0;
331   fCurrLink = 0;
332
333   UChar_t *buffer = 0x0;
334
335   while (fRawReader->ReadNextData(buffer)) {
336
337     fCurrEquipmentId = fRawReader->GetEquipmentId();
338     AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
339
340     if (fCurrEquipmentId < kDDLOffset || fCurrEquipmentId > kDDLMax) {
341       EquipmentError(kNonTrdEq, "Skipping");
342       continue;
343     }
344
345     if (fMarkers)
346       new ((*fMarkers)[fMarkers->GetEntriesFast()])
347         AliTRDrawStreamError(-kSecactive, fCurrEquipmentId - kDDLOffset);
348
349     ReadGTUHeaders((UInt_t*) buffer);
350
351     if (fCurrTrailerReadout)
352       ReadGTUTrailer();
353
354     return kTRUE;
355   }
356
357   return kFALSE;
358 }
359
360
361 Int_t AliTRDrawStream::NextChamber(AliTRDdigitsManager *digMgr)
362 {
363   // read the data for the next chamber
364   // in case you only want to read the data of a single chamber
365   // to read all data ReadEvent(...) is recommended
366
367   fDigitsManager = digMgr;
368   fDigitsParam   = 0x0;
369
370   fErrorFlags = 0;
371
372   // tracklet output preparation
373   TTree *trklTree = 0x0;
374   AliRunLoader *rl = AliRunLoader::Instance();
375   AliLoader* trdLoader = rl ? rl->GetLoader("TRDLoader") : NULL;
376   AliDataLoader *trklLoader = trdLoader ? trdLoader->GetDataLoader("tracklets") : NULL;
377   if (trklLoader) {
378     AliTreeLoader *trklTreeLoader = (AliTreeLoader*) trklLoader->GetBaseLoader("tracklets-raw");
379     if (trklTreeLoader)
380       trklTree = trklTreeLoader->Tree();
381     else
382       trklTree = trklLoader->Tree();
383   }
384
385   if (fTrackletTree != trklTree)
386     ConnectTracklets(trklTree);
387
388   if (!fRawReader) {
389     AliError("No raw reader available");
390     return -1;
391   }
392
393   while (fCurrSlot < 0 || fCurrSlot >= fgkNstacks) {
394     if (!NextDDL()) {
395       fCurrSlot = -1;
396       return -1;
397     }
398     while ((fCurrSlot < fgkNstacks) &&
399            (((fCurrStackMask & (1 << fCurrSlot)) == 0) ||
400             ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0)) {
401       fCurrLink++;
402       if (fCurrLink >= fgkNlinks) {
403         fCurrLink = 0;
404         fCurrSlot++;
405       }
406     }
407   }
408
409   AliDebug(2, Form("Stack %i, Link %i, mask: 0x%02x", fCurrSlot, fCurrLink, fCurrLinkMask[fCurrSlot]));
410   fCurrHC   = (fCurrEquipmentId - kDDLOffset) * fgkNlinks * fgkNstacks +
411     fCurrSlot * fgkNlinks + fCurrLink;
412
413   if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0)
414     LinkError(kLinkMonitor);
415   else
416     // read the data from one HC
417     ReadLinkData();
418
419   // read all data endmarkers
420   SeekNextLink();
421
422   if (fCurrLink % 2 == 0) {
423     // if we just read the A-side HC then also check the B-side
424     fCurrLink++;
425     fCurrHC++;
426     if (fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) {
427       ReadLinkData();
428       SeekNextLink();
429     }
430   }
431
432   //??? to check
433   do {
434     fCurrLink++;
435     if (fCurrLink >= fgkNlinks) {
436       fCurrLink = 0;
437       fCurrSlot++;
438     }
439   } while ((fCurrSlot < fgkNstacks) &&
440            (((fCurrStackMask & (1 << fCurrSlot)) == 0) ||
441             ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0));
442
443   // return chamber information from HC if it is valid
444   // otherwise return information from link position
445   if (fCurrSm < 0 || fCurrSm >= fgkNsectors || fCurrStack < 0 || fCurrStack >= fgkNstacks || fCurrLayer < 0 || fCurrLayer >= fgkNlinks/2)
446     return ((fCurrEquipmentId-kDDLOffset) + fCurrSlot * fgkNlinks/2 + fCurrLink/2);
447   else
448     return (fCurrSm * fgkNstacks*fgkNlinks/2 + fCurrStack * fgkNlinks/2 + fCurrLayer);
449 }
450
451
452 Int_t AliTRDrawStream::ReadGTUHeaders(UInt_t *buffer)
453 {
454   // check the data source and read the headers
455
456   if (fCurrEquipmentId >= kDDLOffset && fCurrEquipmentId <= kDDLMax) {
457     // this is ROC data
458
459     // setting the pointer to data and current reading position
460     fPayloadCurr = fPayloadStart = buffer;
461     fPayloadSize = fRawReader->GetDataSize() / sizeof(UInt_t);
462     fStats.fStatsSector[fCurrEquipmentId - kDDLOffset].fBytes = fRawReader->GetDataSize();
463     AliDebug(2, Form("Read buffer of size: %i", fRawReader->GetDataSize()));
464
465     AliDebug(1, DumpRaw("raw data", fPayloadCurr, TMath::Min(fPayloadSize, 1000)));
466
467     // read SM header
468     if (ReadSmHeader() < 0) {
469       AliError(Form("Reading SM header failed, skipping this DDL %i", fCurrEquipmentId));
470       return -1;
471     }
472
473     // read tracking headers (if available)
474     if (fCurrTrkHeaderAvail) {
475       for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
476         if ((fCurrStackMask & (1 << iStack)) != 0)
477           ReadTrackingHeader(iStack);
478       }
479     }
480
481     // read trigger header(s) (if available)
482     if (fCurrTrgHeaderAvail)
483       ReadTriggerHeaders();
484
485     // read stack header
486     for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
487       if ((fCurrStackMask & (1 << iStack)) != 0)
488         ReadStackHeader(iStack);
489     }
490
491     return 0;
492   }
493   else
494     return -1;
495 }
496
497 Int_t AliTRDrawStream::ReadSmHeader()
498 {
499   // read the SMU index header at the current reading position
500   // and store the information in the corresponding variables
501
502   if (fPayloadCurr - fPayloadStart >= fPayloadSize - 1) {
503     EquipmentError(kUnknown, "SM Header incomplete");
504     return -1;
505   }
506
507   fCurrSmHeaderSize           = ((*fPayloadCurr) >> 16) & 0xffff;
508   fCurrSmHeaderVersion        = ((*fPayloadCurr) >> 12) &    0xf;
509   fCurrTrackEnable            = ((*fPayloadCurr) >>  6) &    0x1;
510   fCurrTrackletEnable         = ((*fPayloadCurr) >>  5) &    0x1;
511   fCurrStackMask              = ((*fPayloadCurr)      ) &   0x1f;
512   fCurrHwRev                  = (fPayloadCurr[1] >> 12) & 0xffff;
513
514   switch (fCurrSmHeaderVersion) {
515   case 0xb:
516     fCurrTrailerReadout = 0;
517     fCurrTrgHeaderAvail = 0;
518     fCurrEvType = 0;
519     fCurrTrkHeaderAvail = 0;
520
521     DecodeGTUtracks();
522     break;
523
524   case 0xc:
525     fCurrTrailerReadout = ((*fPayloadCurr) >> 10) &    0x1;
526     fCurrTrgHeaderAvail = 1;
527     fCurrTrgHeaderReadout = ((*fPayloadCurr) >>  9) &    0x1;
528     fCurrEvType         = ((*fPayloadCurr) >>  7) &    0x3;
529     fCurrTrkHeaderAvail = fCurrTrackEnable;
530     fCurrTriggerEnable  = (fPayloadCurr[2] >>  8) &  0xfff;
531     fCurrTriggerFired   = (fPayloadCurr[2] >>  20) &  0xfff;
532     break;
533
534   default:
535     AliError(Form("unknown SM header version: 0x%x", fCurrSmHeaderVersion));
536   }
537
538   AliDebug(5, Form("SM header: size: %i, version: %i, track enable: %i, tracklet enable: %i, stack mask: %2x, trailer: %i, trgheader: %i, trkheader: %i",
539                    fCurrSmHeaderSize,
540                    fCurrSmHeaderVersion,
541                    fCurrTrackEnable,
542                    fCurrTrackletEnable,
543                    fCurrStackMask,
544                    fCurrTrailerReadout,
545                    fCurrTrgHeaderAvail,
546                    fCurrTrkHeaderAvail ));
547
548   // jump to the first word after the SM header
549   fPayloadCurr += fCurrSmHeaderSize + 1;
550
551   return fCurrSmHeaderSize + 1;
552 }
553
554 Int_t AliTRDrawStream::DecodeGTUtracks()
555 {
556   // decode GTU track words
557   // this depends on the hardware revision of the SMU
558
559   Int_t sector = fCurrEquipmentId-kDDLOffset;
560
561   if ((sector < 0) || (sector > 17)) {
562     AliError(Form("Invalid sector %i for GTU tracks", sector));
563     return -1;
564   }
565
566   AliDebug(1, DumpRaw(Form("GTU tracks in sector %2i (hw rev %i)", sector, fCurrHwRev),
567                       fPayloadCurr + 4, 10, 0xffe0ffff));
568
569   if (fCurrHwRev < 1772) {
570     UInt_t    fastWord;         // fast trigger word
571     ULong64_t trackWord = 0;    // extended track word
572     Int_t stack = 0;
573     Int_t idx = 0;
574     for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
575       if (fPayloadCurr[iWord] == 0x10000000) { // stack boundary marker
576         stack++;
577         idx = 0;
578       }
579       else {
580         if ((idx == 0) &&
581             ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
582           fastWord = fPayloadCurr[iWord];
583           AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
584           continue;
585         }
586         else if ((idx & 0x1) == 0x1) {
587           trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
588           AliDebug(1,Form("track debug word: 0x%016llx", trackWord));
589           if (fTracks) {
590             AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
591               AliESDTrdTrack();
592
593             trk->SetSector(sector);
594             trk->SetStack((trackWord >> 60) & 0x7);
595             trk->SetA(0);
596             trk->SetB(0);
597             trk->SetPID(0);
598             trk->SetLayerMask((trackWord >> 16) & 0x3f);
599             trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
600             trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
601             trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
602             trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
603             trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
604             trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
605
606             trk->SetFlags(0);
607             trk->SetReserved(0);
608
609             Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
610             if (TMath::Abs(pt) > 0.1) {
611               trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
612             }
613           }
614         }
615         else {
616           trackWord = fPayloadCurr[iWord];
617         }
618         idx++;
619       }
620     }
621   }
622   else if (fCurrHwRev < 1804) {
623     UInt_t    fastWord;         // fast trigger word
624     ULong64_t trackWord = 0;    // extended track word
625     Int_t stack = 0;
626     Int_t idx = 0;
627     for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
628       if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
629         stack++;
630         idx = 0;
631       }
632       else {
633         if ((idx == 0) &&
634             ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
635           fastWord = fPayloadCurr[iWord];
636           AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
637           continue;
638         }
639         else if ((idx & 0x1) == 0x1) {
640           trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
641           AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
642           if (fTracks) {
643             AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
644               AliESDTrdTrack();
645
646             trk->SetSector(fCurrEquipmentId-kDDLOffset);
647             trk->SetStack((trackWord >> 60) & 0x7);
648             trk->SetA(0);
649             trk->SetB(0);
650             trk->SetPID(0);
651             trk->SetLayerMask((trackWord >> 16) & 0x3f);
652             trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
653             trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
654             trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
655             trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
656             trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
657             trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
658
659             trk->SetFlags(0);
660             trk->SetReserved(0);
661
662             Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
663             if (TMath::Abs(pt) > 0.1) {
664               trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
665             }
666           }
667         }
668         else {
669           trackWord = fPayloadCurr[iWord];
670         }
671         idx++;
672       }
673     }
674   }
675   else if (fCurrHwRev < 1819) {
676     UInt_t    fastWord;         // fast trigger word
677     ULong64_t trackWord = 0;    // extended track word
678     Int_t stack = 0;
679     Int_t idx = 0;
680     for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
681       if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
682         stack++;
683         idx = 0;
684       }
685       else {
686         if ((idx == 0) &&
687             ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
688           fastWord = fPayloadCurr[iWord];
689           AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
690           continue;
691         }
692         else if ((idx & 0x1) == 0x1) {
693           trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
694           AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
695
696           if (fTracks) {
697             AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
698               AliESDTrdTrack();
699
700             trk->SetSector(fCurrEquipmentId-kDDLOffset);
701             trk->SetStack((trackWord >> 60) & 0x7);
702             trk->SetA(0);
703             trk->SetB(0);
704             // trk->SetPt(((trackWord & 0xffff) ^ 0x8000) - 0x8000);
705             trk->SetPID(0);
706             trk->SetLayerMask((trackWord >> 16) & 0x3f);
707             trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
708             trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
709             trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
710             trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
711             trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
712             trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
713
714             trk->SetFlags(0);
715             trk->SetReserved(0);
716
717             Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
718             if (TMath::Abs(pt) > 0.1) {
719               trk->SetA((Int_t) (0.15*51625./100./trk->Pt() / 160e-4 * 2));
720             }
721           }
722         }
723         else {
724           trackWord = fPayloadCurr[iWord];
725         }
726         idx++;
727       }
728     }
729   }
730   else if (fCurrHwRev < 1860) {
731     UInt_t    fastWord;         // fast trigger word
732     ULong64_t trackWord = 0;    // extended track word
733     Int_t stack = 0;
734     Int_t idx = 0;
735     Bool_t upperWord = kFALSE;
736     Int_t word = 0;
737     for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
738       if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
739         stack++;
740         idx = 0;
741         upperWord = kFALSE;
742       }
743       else {
744         // assemble the 32-bit words out of 16-bit blocks
745         if (upperWord) {
746           word |= (fPayloadCurr[iWord] & 0xffff0000);
747           upperWord = kFALSE;
748         }
749         else {
750           // lower word is read first
751           word = (fPayloadCurr[iWord] & 0xffff0000) >> 16;
752           upperWord = kTRUE;
753           continue;
754         }
755
756         if ((word & 0xffff0008) == 0x13370008) {
757           fastWord = word;
758           AliDebug(1, Form("stack %i: fast track word: 0x%08x", stack, fastWord));
759           continue;
760         }
761         else if ((idx & 0x1) == 0x1) {
762           trackWord |= ((ULong64_t) word) << 32;
763           AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
764           if (fTracks) {
765             AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
766               AliESDTrdTrack();
767
768             trk->SetSector(fCurrEquipmentId-kDDLOffset);
769             trk->SetStack((trackWord >> 60) & 0x7);
770             trk->SetA(0);
771             trk->SetB(0);
772             trk->SetPID(0);
773             trk->SetLayerMask((trackWord >> 16) & 0x3f);
774             trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
775             trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
776             trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
777             trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
778             trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
779             trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
780
781             trk->SetFlags(0);
782             trk->SetReserved(0);
783
784             Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
785             if (TMath::Abs(pt) > 0.1) {
786               trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
787             }
788           }
789         }
790         else {
791           trackWord = word;
792         }
793         idx++;
794       }
795     }
796
797   }
798   else {
799     ULong64_t trackWord = 0; // this is the debug word
800     Int_t stack = 0;
801     Int_t idx = 0;
802     Bool_t upperWord = kFALSE;
803     Int_t word = 0;
804     for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
805       if (fPayloadCurr[iWord] == 0xffe0ffff) {
806         stack++;
807         idx = 0;
808         upperWord = kFALSE;
809       }
810       else {
811         // assemble the 32-bit words out of 16-bit blocks
812         if (upperWord) {
813           word |= (fPayloadCurr[iWord] & 0xffff0000);
814           upperWord = kFALSE;
815         }
816         else {
817           // lower word is read first
818           word = (fPayloadCurr[iWord] & 0xffff0000) >> 16;
819           upperWord = kTRUE;
820           continue;
821         }
822
823         if ((word & 0xffff0008) == 0x13370008) {
824           AliDebug(1, Form("stack %i: fast track word: 0x%08x", stack, word));
825           continue;
826         }
827         else if ((word & 0xffff0010) == 0x13370010) {
828           AliDebug(1, Form("stack %i: tracking done word: 0x%08x", stack, word));
829           continue;
830         }
831         else if ((idx & 0x1) == 0x1) {
832           trackWord |= ((ULong64_t) word) << 32;
833           AliDebug(1, Form("track debug word: 0x%16llx", trackWord));
834           if (fTracks) {
835             AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
836               AliESDTrdTrack();
837             trk->SetSector(fCurrEquipmentId-kDDLOffset);
838             trk->SetStack((trackWord >> 60) & 0x7);
839             trk->SetA(0);
840             trk->SetB(0);
841             trk->SetPID(0);
842             trk->SetLayerMask((trackWord >> 16) & 0x3f);
843             trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
844             trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
845             trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
846             trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
847             trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
848             trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
849
850             trk->SetFlags(0);
851             trk->SetReserved(0);
852
853             Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
854             if (TMath::Abs(pt) > 0.1) {
855               trk->SetA(-(Int_t) (0.15*51625./100./pt / 160e-4 * 2));
856             }
857           }
858         }
859         else {
860           trackWord = word;
861         }
862         idx++;
863       }
864     }
865   }
866   return 0;
867 }
868
869 Int_t AliTRDrawStream::ReadTrackingHeader(Int_t stack)
870 {
871   // read the tracking information and store it for the given stack
872
873   // index word
874
875   fCurrTrkHeaderIndexWord[stack] = *fPayloadCurr;
876   fCurrTrkHeaderSize[stack]      = ((*fPayloadCurr) >> 16) & 0x3ff;
877
878   AliDebug(1, Form("tracking header index word: 0x%08x, size: %i (hw rev: %i)",
879                    fCurrTrkHeaderIndexWord[stack], fCurrTrkHeaderSize[stack], fCurrHwRev));
880   Int_t trackingTime = *fPayloadCurr & 0x3ff;
881
882   fPayloadCurr++;
883
884   // data words
885   ULong64_t trackWord = 0;
886   Int_t idx = 0;
887   Int_t trackIndex = fTracks ? fTracks->GetEntriesFast() : -1;
888
889   for (UInt_t iWord = 0; iWord < fCurrTrkHeaderSize[stack]; iWord++) {
890
891     if (!(idx & 0x1)) {
892       // first part of 64-bit word
893       trackWord = fPayloadCurr[iWord];
894     }
895     else {
896       trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
897
898       if (trackWord & (1ul << 63)) {
899         if ((trackWord & (0x3ful << 56)) != 0) {
900           // track word
901           AliDebug(2, Form("track word: 0x%016llx", trackWord));
902
903           if (fTracks) {
904             AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
905               AliESDTrdTrack();
906
907             trk->SetSector(fCurrEquipmentId-kDDLOffset);
908             trk->SetLayerMask((trackWord >> 56) & 0x3f);
909             trk->SetA( (((trackWord >> 38) & 0x3ffff) ^ 0x20000) - 0x20000);
910             trk->SetB( (((trackWord >> 20) & 0x3ffff) ^ 0x20000) - 0x20000);
911             trk->SetC( (((trackWord >> 8)  &  0xffff) ^  0x8000) -  0x8000);
912             trk->SetPID((trackWord >>  0) & 0xff);
913             trk->SetStack(stack);
914
915             // now compare the track word with the one generated from the ESD information
916             if (trackWord != trk->GetTrackWord(0)) {
917               AliError(Form("track word 0x%016llx does not match the read one 0x%016llx",
918                             trk->GetTrackWord(0), trackWord));
919             }
920           }
921         }
922         else {
923           // done marker (so far only used to set trigger flag)
924
925           AliDebug(2, Form("seg / stack / first / last / done / index : %i %i %lli %lli %lli %i",
926                            fCurrEquipmentId - kDDLOffset, stack,
927                            (trackWord >> 20) & 0x3ff,
928                            (trackWord >> 10) & 0x3ff,
929                            (trackWord >>  0) & 0x3ff,
930                            trackingTime));
931         }
932       }
933       else {
934         // extended track word
935         AliDebug(2, Form("extended track word: 0x%016llx", trackWord));
936
937         if (fTracks) {
938           AliESDTrdTrack *trk = (AliESDTrdTrack*) (*fTracks)[trackIndex];
939
940           trk->SetFlags((trackWord >> 52) & 0x7ff);
941           trk->SetReserved((trackWord >> 49) & 0x7);
942           trk->SetY((trackWord >> 36) & 0x1fff);
943           trk->SetTrackletIndex((trackWord >>  0) & 0x3f, 0);
944           trk->SetTrackletIndex((trackWord >>  6) & 0x3f, 1);
945           trk->SetTrackletIndex((trackWord >> 12) & 0x3f, 2);
946           trk->SetTrackletIndex((trackWord >> 18) & 0x3f, 3);
947           trk->SetTrackletIndex((trackWord >> 24) & 0x3f, 4);
948           trk->SetTrackletIndex((trackWord >> 30) & 0x3f, 5);
949
950           if (trackWord != trk->GetExtendedTrackWord(0)) {
951             AliError(Form("extended track word 0x%016llx does not match the read one 0x%016llx",
952                           trk->GetExtendedTrackWord(0), trackWord));
953             }
954
955           trackIndex++;
956         }
957       }
958     }
959     idx++;
960   }
961
962   fPayloadCurr += fCurrTrkHeaderSize[stack];
963
964   return fCurrTrkHeaderSize[stack];
965 }
966
967 Int_t AliTRDrawStream::ReadTriggerHeaders()
968 {
969   // read all trigger headers present
970
971   AliDebug(1, Form("trigger mask: 0x%03x, fired: 0x%03x\n",
972                    fCurrTriggerEnable, fCurrTriggerFired));
973   // loop over potential trigger blocks
974   for (Int_t iTrigger = 0; iTrigger < fgkNtriggers; iTrigger++) {
975     // check for trigger enable
976     if (fCurrTriggerEnable & (1 << iTrigger)) {
977       // check for readout mode and trigger fired
978       if ((fCurrTrgHeaderReadout == 0) || (fCurrTriggerFired & (1 << iTrigger))) {
979         // index word
980         AliDebug(1, Form("trigger index word %i: 0x%08x\n", iTrigger, *fPayloadCurr));
981         fCurrTrgHeaderIndexWord[iTrigger] = *fPayloadCurr;
982         fCurrTrgHeaderSize[iTrigger]      = ((*fPayloadCurr) >> 16) & 0x3ff;
983         fPayloadCurr++;
984         // data words
985         fPayloadCurr += fCurrTrgHeaderSize[iTrigger];
986       }
987     }
988   }
989
990   return 0;
991 }
992
993 Int_t AliTRDrawStream::ReadStackHeader(Int_t stack)
994 {
995   // read the stack header
996   // and store the information in the corresponding variables
997
998   fCurrStackIndexWord[stack]     = *fPayloadCurr;
999   fCurrStackHeaderSize[stack]    = (((*fPayloadCurr) >> 16) & 0xffff) + 1;
1000   fCurrStackHeaderVersion[stack] = ((*fPayloadCurr) >> 12) & 0xf;
1001   fCurrLinkMask[stack]           = (*fPayloadCurr) & 0xfff;
1002
1003   // dumping stack header
1004   AliDebug(1, DumpRaw(Form("stack %i header", stack), fPayloadCurr, fCurrStackHeaderSize[stack]));
1005
1006   if (fPayloadCurr - fPayloadStart >= fPayloadSize - (Int_t) fCurrStackHeaderSize[stack]) {
1007     LinkError(kStackHeaderInvalid, "Stack index header aborted");
1008     return -1;
1009   }
1010
1011   switch (fCurrStackHeaderVersion[stack]) {
1012   case 0xa:
1013     if (fCurrStackHeaderSize[stack] < 8) {
1014       LinkError(kStackHeaderInvalid, "Stack header smaller than expected!");
1015       return -1;
1016     }
1017
1018     fCurrCleanCheckout[stack] = fPayloadCurr[1] & 0x1;
1019     fCurrBoardId[stack]       = (fPayloadCurr[1] >> 8) & 0xff;
1020     fCurrHwRevTMU[stack]      = (fPayloadCurr[1] >> 16) & 0xffff;
1021
1022     for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
1023       // A side
1024       fCurrLinkMonitorFlags  [stack*fgkNlinks + iLayer*2]      = fPayloadCurr[iLayer+2] & 0xf;
1025       fCurrLinkDataTypeFlags [stack*fgkNlinks + iLayer*2]      = (fPayloadCurr[iLayer+2] >> 4) & 0x3;
1026       fCurrLinkDebugFlags    [stack*fgkNlinks + iLayer*2]      = (fPayloadCurr[iLayer+2] >> 12) & 0xf;
1027       // B side
1028       fCurrLinkMonitorFlags  [stack*fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 16) & 0xf;
1029       fCurrLinkDataTypeFlags [stack*fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 20) & 0x3;
1030       fCurrLinkDebugFlags    [stack*fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 28) & 0xf;
1031     }
1032     break;
1033
1034   default:
1035     LinkError(kStackHeaderInvalid, "Invalid Stack Header version %x", fCurrStackHeaderVersion[stack]);
1036   }
1037
1038   fPayloadCurr += fCurrStackHeaderSize[stack];
1039
1040   return fCurrStackHeaderSize[stack];
1041 }
1042
1043 Int_t AliTRDrawStream::ReadGTUTrailer()
1044 {
1045   // read the SM trailer containing CRCs from various stages
1046
1047   UInt_t* trailer = fPayloadStart + fPayloadSize -1;
1048
1049   // look for the trailer index word from the end
1050   for (Int_t iWord = 0; iWord < fPayloadSize; iWord++) {
1051     if ((fPayloadStart[fPayloadSize-1-iWord] & 0xffff) == 0x1f51) {
1052       trailer = fPayloadStart + fPayloadSize - 1 - iWord;
1053       break;
1054     }
1055   }
1056
1057   if (((*trailer) & 0xffff) == 0x1f51) {
1058     UInt_t trailerIndexWord = (*trailer);
1059     Int_t trailerSize = (trailerIndexWord >> 16) & 0xffff;
1060     AliDebug(2, DumpRaw("GTU trailer", trailer, trailerSize+1));
1061     // parse the trailer
1062   }
1063   else
1064     EquipmentError(kUnknown, "trailer index marker mismatch");
1065
1066   return 0;
1067 }
1068
1069 Int_t AliTRDrawStream::ReadLinkData()
1070 {
1071   // read the data in one link (one HC) until the data endmarker is reached
1072   // returns the number of words read!
1073
1074   Int_t count = 0;
1075   UInt_t* startPosLink = fPayloadCurr;
1076
1077   AliDebug(1, DumpRaw(Form("link data from seg %2i slot %i link %2i", fCurrEquipmentId-kDDLOffset, fCurrSlot, fCurrLink),
1078                       fPayloadCurr, TMath::Min((Int_t) (fPayloadSize - (fPayloadCurr-fPayloadStart)), 100), 0x00000000));
1079
1080   if (fMarkers)
1081     new ((*fMarkers)[fMarkers->GetEntriesFast()])
1082       AliTRDrawStreamError(-kHCactive, fCurrEquipmentId-kDDLOffset, fCurrStack, fCurrLink);
1083
1084   if (fErrorFlags & kDiscardHC)
1085     return count;
1086
1087   //??? add check whether tracklets are enabled
1088   count += ReadTracklets();
1089   if (fErrorFlags & kDiscardHC)
1090     return count;
1091
1092   AliDebug(1, DumpRaw("HC header", fPayloadCurr, 4, 0x00000000));
1093   count += ReadHcHeader();
1094   if (fErrorFlags & kDiscardHC)
1095     return count;
1096
1097   Int_t det = fCurrSm * 30 + fCurrStack * 6 + fCurrLayer;
1098
1099   if (det > -1 && det < 540) {
1100
1101     if ((fAdcArray = fDigitsManager->GetDigits(det))) {
1102       //fAdcArray->Expand();
1103       if (fAdcArray->GetNtime() != fCurrNtimebins)
1104         fAdcArray->Allocate(16, 144, fCurrNtimebins);
1105     }
1106     else {
1107       LinkError(kNoDigits);
1108     }
1109
1110     if (!fDigitsParam) {
1111       fDigitsParam = fDigitsManager->GetDigitsParam();
1112     }
1113     if (fDigitsParam) {
1114       fDigitsParam->SetPretriggerPhase(det, fCurrPtrgPhase);
1115       fDigitsParam->SetNTimeBins(det, fCurrNtimebins);
1116       fDigitsParam->SetADCbaseline(det, 10);
1117     }
1118
1119     if (fDigitsManager->UsesDictionaries()) {
1120       fDigitsManager->GetDictionary(det, 0)->Reset();
1121       fDigitsManager->GetDictionary(det, 1)->Reset();
1122       fDigitsManager->GetDictionary(det, 2)->Reset();
1123     }
1124
1125     if ((fSignalIndex = fDigitsManager->GetIndexes(det))) {
1126       fSignalIndex->SetSM(fCurrSm);
1127       fSignalIndex->SetStack(fCurrStack);
1128       fSignalIndex->SetLayer(fCurrLayer);
1129       fSignalIndex->SetDetNumber(det);
1130       if (!fSignalIndex->IsAllocated())
1131         fSignalIndex->Allocate(16, 144, fCurrNtimebins);
1132     }
1133
1134     // ----- check which kind of data -----
1135     if (fCurrMajor & 0x40) {
1136       if ((fCurrMajor & 0x7) == 0x7) {
1137         AliDebug(1, "This is a config event");
1138         UInt_t *startPos = fPayloadCurr;
1139         while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1140                *fPayloadCurr != fgkDataEndmarker)
1141           fPayloadCurr++;
1142         count += fPayloadCurr - startPos;
1143
1144         // feeding TRAP config
1145         AliTRDtrapConfig *trapcfg = AliTRDtrapConfig::Instance();
1146         trapcfg->ReadPackedConfig(fCurrHC, startPos, fPayloadCurr - startPos);
1147       }
1148       else {
1149         Int_t tpmode = fCurrMajor & 0x7;
1150         AliDebug(1, Form("Checking testpattern (mode %i) data", tpmode));
1151         ReadTPData(tpmode);
1152       }
1153     }
1154     else if (fCurrMajor & 0x20) {
1155       AliDebug(1, "This is a zs event");
1156       count += ReadZSData();
1157     }
1158     else {
1159       AliDebug(1, "This is a nozs event");
1160       count += ReadNonZSData();
1161     }
1162   }
1163   else {
1164     LinkError(kInvalidDetector, "%i", det);
1165     while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1166            *fPayloadCurr != fgkDataEndmarker)
1167       fPayloadCurr++;
1168   }
1169
1170   if (fCurrSm > -1 && fCurrSm < 18) {
1171     fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytes     += (fPayloadCurr - startPosLink) * sizeof(UInt_t);
1172     fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytesRead += count * sizeof(UInt_t);
1173     fStats.fStatsSector[fCurrSm].fBytesRead                      += count * sizeof(UInt_t);
1174     fStats.fBytesRead                                            += count * sizeof(UInt_t);
1175   }
1176
1177   return count;
1178 }
1179
1180 Int_t AliTRDrawStream::ReadTracklets()
1181 {
1182   // read the tracklets from one HC
1183
1184   fTrackletArray->Clear();
1185
1186   UInt_t *start = fPayloadCurr;
1187   while (*(fPayloadCurr) != fgkTrackletEndmarker &&
1188          fPayloadCurr - fPayloadStart < fPayloadSize) {
1189     new ((*fTrackletArray)[fTrackletArray->GetEntriesFast()]) AliTRDtrackletWord(*(fPayloadCurr), fCurrHC);
1190
1191     fPayloadCurr++;
1192   }
1193
1194   if (fTrackletArray->GetEntriesFast() > 0) {
1195     AliDebug(1, Form("Found %i tracklets in %i %i %i (ev. %i)", fTrackletArray->GetEntriesFast(),
1196                      (fCurrEquipmentId-kDDLOffset), fCurrSlot, fCurrLink, fRawReader->GetEventIndex()));
1197     if (fCurrSm > -1 && fCurrSm < 18) {
1198       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNTracklets += fTrackletArray->GetEntriesFast();
1199       fStats.fStatsSector[fCurrSm].fNTracklets                      += fTrackletArray->GetEntriesFast();
1200     }
1201     if (fTrackletTree)
1202       fTrackletTree->Fill();
1203     if (fTracklets)
1204       for (Int_t iTracklet = 0; iTracklet < fTrackletArray->GetEntriesFast(); iTracklet++) {
1205         new ((*fTracklets)[fTracklets->GetEntriesFast()]) AliTRDtrackletWord(*((AliTRDtrackletWord*)(*fTrackletArray)[iTracklet]));
1206       }
1207   }
1208
1209   // loop over remaining tracklet endmarkers
1210   while ((*(fPayloadCurr) == fgkTrackletEndmarker &&
1211           fPayloadCurr - fPayloadStart < fPayloadSize))
1212     fPayloadCurr++;
1213
1214   return fPayloadCurr - start;
1215 }
1216
1217 Int_t AliTRDrawStream::ReadHcHeader()
1218 {
1219   // read and parse the HC header of one HC
1220   // and store the information in the corresponding variables
1221
1222   AliDebug(1, Form("HC header: 0x%08x", *fPayloadCurr));
1223   UInt_t *start = fPayloadCurr;
1224   // check not to be at the data endmarker
1225   if (*fPayloadCurr == fgkDataEndmarker)
1226     return 0;
1227
1228   fCurrSpecial    = (*fPayloadCurr >> 31) & 0x1;
1229   fCurrMajor      = (*fPayloadCurr >> 24) & 0x7f;
1230   fCurrMinor      = (*fPayloadCurr >> 17) & 0x7f;
1231   fCurrAddHcWords = (*fPayloadCurr >> 14) & 0x7;
1232   fCurrSm         = (*fPayloadCurr >> 9) & 0x1f;
1233   fCurrLayer      = (*fPayloadCurr >> 6) & 0x7;
1234   fCurrStack      = (*fPayloadCurr >> 3) & 0x7;
1235   fCurrSide       = (*fPayloadCurr >> 2) & 0x1;
1236   fCurrCheck      = (*fPayloadCurr) & 0x3;
1237
1238   if ((fCurrSm != (((Int_t) fCurrEquipmentId) - kDDLOffset)) ||
1239       (fCurrStack != fCurrSlot) ||
1240       (fCurrLayer != fCurrLink / 2) ||
1241       (fCurrSide != fCurrLink % 2)) {
1242     LinkError(kHCmismatch,
1243               "HC: %i, %i, %i, %i\n 0x%08x 0x%08x 0x%08x 0x%08x",
1244               fCurrSm, fCurrStack, fCurrLayer, fCurrSide,
1245               fPayloadCurr[0], fPayloadCurr[1], fPayloadCurr[2], fPayloadCurr[3]);
1246   }
1247   if (fCurrCheck != 0x1) {
1248     LinkError(kHCcheckFailed);
1249   }
1250
1251   if (fCurrAddHcWords > 0) {
1252     fCurrNtimebins = (fPayloadCurr[1] >> 26) & 0x3f;
1253     fCurrBC = (fPayloadCurr[1] >> 10) & 0xffff;
1254     fCurrPtrgCnt = (fPayloadCurr[1] >> 6) & 0xf;
1255     fCurrPtrgPhase = (fPayloadCurr[1] >> 2) & 0xf;
1256   }
1257
1258   fPayloadCurr += 1 + fCurrAddHcWords;
1259
1260   return (fPayloadCurr - start);
1261 }
1262
1263 Int_t AliTRDrawStream::ReadTPData(Int_t mode)
1264 {
1265   // testing of testpattern 1 to 3 (hardcoded), 0 missing
1266   // evcnt checking missing
1267   Int_t cpu = 0;
1268   Int_t cpufromchannel[] = {0, 0, 0, 0, 0,  1, 1, 1, 1, 1,  2, 2, 2, 2, 2,  3, 3, 3, 3, 3, 3};
1269   Int_t evcnt = 0;
1270   Int_t count = 0;
1271   Int_t mcmcount = -1;
1272   Int_t wordcount = 0;
1273   Int_t channelcount = 0;
1274   UInt_t expword = 0;
1275   UInt_t expadcval = 0;
1276   UInt_t diff = 0;
1277   Int_t lastmcmpos = -1;
1278   Int_t lastrobpos = -1;
1279
1280   UInt_t* start = fPayloadCurr;
1281
1282   while (*(fPayloadCurr) != fgkDataEndmarker &&
1283          fPayloadCurr - fPayloadStart < fPayloadSize - 1) {
1284
1285     // ----- Checking MCM Header -----
1286     AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
1287     mcmcount++;
1288
1289     // ----- checking for proper readout order - ROB -----
1290     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1291       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1292     }
1293     else {
1294       ROBError(kPosUnexp, Form("#%i after #%i in readout order", GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos));
1295     }
1296     fCurrRobPos = ROB(*fPayloadCurr);
1297
1298     // ----- checking for proper readout order - MCM -----
1299     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) >= (lastmcmpos + 1) % 16) {
1300       lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
1301     }
1302     else {
1303       MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
1304     }
1305     fCurrMcmPos = MCM(*fPayloadCurr);
1306
1307
1308     fPayloadCurr++;
1309
1310     evcnt = 0x3f & *fPayloadCurr >> 26;
1311     cpu = -1;
1312     channelcount = 0;
1313     while (channelcount < 21) {
1314       count = 0;
1315       if (cpu != cpufromchannel[channelcount]) {
1316         cpu = cpufromchannel[channelcount];
1317         expadcval = (1 << 9) | (fCurrRobPos << 6) | (fCurrMcmPos << 2) | cpu;
1318         wordcount = 0;
1319       }
1320
1321       while (count < 10) {
1322         if (channelcount % 2 == 0)
1323           expword = 0x3;
1324         else
1325           expword = 0x2;
1326
1327         if (mode == 1) {
1328           // ----- TP 1 -----
1329           expword |= expadcval << 2;
1330           expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
1331           expword |= expadcval << 12;
1332           expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
1333           expword |= expadcval << 22;
1334           expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
1335         }
1336         else if (mode == 2) {
1337           // ----- TP 2 ------
1338           expword = ((0x3f & evcnt) << 26) | ((fCurrSm + 1) << 21) | ((fCurrLayer + 1) << 18) |
1339             ((fCurrStack + 1) << 15) |
1340             (fCurrRobPos << 12) | (fCurrMcmPos << 8) | (cpu << 6) | (wordcount + 1);
1341         }
1342         else if (mode == 3) {
1343           // ----- TP 3 -----
1344           expword = ((0xfff & evcnt) << 20) | (fCurrSm << 15) | (fCurrLink/2 << 12) | (fCurrStack << 9) |
1345             (fCurrRobPos << 6) | (fCurrMcmPos << 2) | (cpu << 0);
1346         }
1347         else {
1348           expword = 0;
1349           LinkError(kTPmodeInvalid, "Just reading");
1350         }
1351
1352         diff = *fPayloadCurr ^ expword;
1353         if (diff != 0) {
1354           MCMError(kTPmismatch,
1355                    "Seen 0x%08x, expected 0x%08x, diff: 0x%08x (0x%02x)",
1356                    *fPayloadCurr, expword, diff, 0xff & (diff | diff >> 8 | diff >> 16 | diff >> 24));;
1357         }
1358         fPayloadCurr++;
1359         count++;
1360         wordcount++;
1361       }
1362       channelcount++;
1363     }
1364     // continue with next MCM
1365   }
1366   return fPayloadCurr - start;
1367 }
1368
1369
1370 Int_t AliTRDrawStream::ReadZSData()
1371 {
1372   // read the zs data from one link from the current reading position
1373
1374   UInt_t *start = fPayloadCurr;
1375
1376   Int_t mcmcount = 0;
1377   Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
1378   Int_t channelcount = 0;
1379   Int_t channelcountExp = 0;
1380   Int_t channelcountMax = 0;
1381   Int_t timebins;
1382   Int_t currentTimebin = 0;
1383   Int_t adcwc = 0;
1384   Int_t evno = -1;
1385   Int_t lastmcmpos = -1;
1386   Int_t lastrobpos = -1;
1387
1388   if (fCurrNtimebins != fNtimebins) {
1389     if (fNtimebins > 0)
1390       LinkError(kNtimebinsChanged,
1391                 "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
1392     fNtimebins = fCurrNtimebins;
1393   }
1394
1395   timebins = fNtimebins;
1396
1397   while (*(fPayloadCurr) != fgkDataEndmarker &&
1398          fPayloadCurr - fPayloadStart < fPayloadSize) {
1399
1400     // ----- Checking MCM Header -----
1401     AliDebug(2, DumpMcmHeader("MCM header: ", *fPayloadCurr));
1402     UInt_t *startPosMCM = fPayloadCurr;
1403
1404     // ----- checking for proper readout order - ROB -----
1405     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1406       if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
1407         lastmcmpos = -1;
1408       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1409     }
1410     else {
1411       ROBError(kPosUnexp, Form("#%i after #%i and #%i in readout order",
1412                                GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos, GetROBReadoutPos(fCurrRobPos)));
1413     }
1414     fCurrRobPos = ROB(*fPayloadCurr);
1415
1416     // ----- checking for proper readout order - MCM -----
1417     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
1418       lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
1419     }
1420     else {
1421       MCMError(kPosUnexp, Form("#%i after #%i and #%i in readout order",
1422                                GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos, GetMCMReadoutPos(fCurrMcmPos)));
1423     }
1424     fCurrMcmPos = MCM(*fPayloadCurr);
1425
1426     if (EvNo(*fPayloadCurr) != evno) {
1427       if (evno == -1)
1428         evno = EvNo(*fPayloadCurr);
1429       else {
1430         MCMError(kPtrgCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
1431       }
1432     }
1433     Int_t adccoloff = AdcColOffset(*fPayloadCurr);
1434     Int_t padcoloff = PadColOffset(*fPayloadCurr);
1435     Int_t row = Row(*fPayloadCurr);
1436     fPayloadCurr++;
1437
1438     // ----- Reading ADC channels -----
1439     AliDebug(2, DumpAdcMask("ADC mask: ", *fPayloadCurr));
1440
1441     // ----- analysing the ADC mask -----
1442     channelcount = 0;
1443     channelcountExp = GetNActiveChannelsFromMask(*fPayloadCurr);
1444     channelcountMax = GetNActiveChannels(*fPayloadCurr);
1445     Int_t channelmask = GetActiveChannels(*fPayloadCurr);
1446     Int_t channelno = -1;
1447     fPayloadCurr++;
1448
1449     if (channelcountExp != channelcountMax) {
1450       if (channelcountExp > channelcountMax) {
1451         Int_t temp = channelcountExp;
1452         channelcountExp = channelcountMax;
1453         channelcountMax = temp;
1454       }
1455       while (channelcountExp < channelcountMax && channelcountExp < 21 &&
1456              fPayloadCurr - fPayloadStart < fPayloadSize - 10 * channelcountExp - 1) {
1457         MCMError(kAdcMaskInconsistent,
1458                  "Possible MCM-H: 0x%08x, possible ADC-mask: 0x%08x",
1459                  *(fPayloadCurr + 10 * channelcountExp),
1460                  *(fPayloadCurr + 10 * channelcountExp + 1) );
1461         if (!CouldBeMCMhdr( *(fPayloadCurr + 10 * channelcountExp)) && !CouldBeADCmask( *(fPayloadCurr + 10 * channelcountExp + 1)))
1462           channelcountExp++;
1463         else {
1464           break;
1465         }
1466       }
1467       MCMError(kAdcMaskInconsistent,
1468                "Inconsistency in no. of active channels: Counter: %i, Mask: %i, chosen: %i!",
1469                GetNActiveChannels(fPayloadCurr[-1]), GetNActiveChannelsFromMask(fPayloadCurr[-1]), channelcountExp);
1470     }
1471     AliDebug(2, Form("expecting %i active channels, %i timebins", channelcountExp, fCurrNtimebins));
1472
1473     // ----- reading marked ADC channels -----
1474     while (channelcount < channelcountExp && *(fPayloadCurr) != fgkDataEndmarker) {
1475       if (channelno < 20)
1476         channelno++;
1477       while (channelno < 20 && (channelmask & 1 << channelno) == 0)
1478         channelno++;
1479
1480       if (fCurrNtimebins > 30) {
1481         currentTimebin = ((*fPayloadCurr >> 2) & 0x3f);
1482         timebins = ((*fPayloadCurr >> 8) & 0xf) * 3;
1483       }
1484       else {
1485         currentTimebin = 0;
1486       }
1487
1488       adcwc = 0;
1489       Int_t nADCwords = (timebins + 2) / 3;
1490       AliDebug(3, Form("Now reading %i words for channel %2i", nADCwords, channelno));
1491       Int_t adccol = adccoloff - channelno;
1492       Int_t padcol = padcoloff - channelno;
1493 //      if (adccol < 3 || adccol > 165)
1494 //      AliInfo(Form("writing channel %i of det %3i %i:%2i to adcrow/-col: %i/%i padcol: %i",
1495 //                   channelno, fCurrHC/2, fCurrRobPos, fCurrMcmPos, row, adccol, padcol));
1496
1497       while ((adcwc < nADCwords) &&
1498              (*(fPayloadCurr) != fgkDataEndmarker) &&
1499              (fPayloadCurr - fPayloadStart < fPayloadSize)) {
1500         int check = 0x3 & *fPayloadCurr;
1501         if (channelno % 2 != 0) { // odd channel
1502           if (check != 0x2 && channelno < 21) {
1503             MCMError(kAdcCheckInvalid,
1504                      "%i for %2i. ADC word in odd channel %i",
1505                      check, adcwc+1, channelno);
1506           }
1507         }
1508         else {                  // even channel
1509           if (check != 0x3 && channelno < 21) {
1510             MCMError(kAdcCheckInvalid,
1511                      "%i for %2i. ADC word in even channel %i",
1512                      check, adcwc+1, channelno);
1513           }
1514         }
1515
1516         // filling the actual timebin data
1517         int tb2 = 0x3ff & *fPayloadCurr >> 22;
1518         int tb1 = 0x3ff & *fPayloadCurr >> 12;
1519         int tb0 = 0x3ff & *fPayloadCurr >> 2;
1520         if (adcwc != 0 || fCurrNtimebins <= 30)
1521           fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
1522         else
1523           tb0 = -1;
1524         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
1525         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
1526
1527         adcwc++;
1528         fPayloadCurr++;
1529       }
1530
1531       if (adcwc != nADCwords)
1532         MCMError(kAdcDataAbort);
1533
1534       // adding index
1535       if (padcol > 0 && padcol < 144) {
1536         fSignalIndex->AddIndexRC(row, padcol);
1537       }
1538
1539       channelcount++;
1540     }
1541
1542     if (fCurrSm > -1 && fCurrSm < 18) {
1543       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNChannels += channelcount;
1544       fStats.fStatsSector[fCurrSm].fNChannels                      += channelcount;
1545     }
1546     if (channelcount != channelcountExp)
1547       MCMError(kAdcChannelsMiss);
1548
1549     mcmcount++;
1550     if (fCurrSm > -1 && fCurrSm < 18) {
1551       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNMCMs++;
1552       fStats.fStatsSector[fCurrSm].fNMCMs++;
1553     }
1554
1555     if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
1556       AliInfo(DumpRaw(Form("Event %i: Det %3i ROB %i MCM %2i", fRawReader->GetEventIndex(), fCurrHC/2, fCurrRobPos, fCurrMcmPos),
1557                       startPosMCM, fPayloadCurr - startPosMCM));
1558     }
1559
1560     // continue with next MCM
1561   }
1562
1563   // check for missing MCMs (if header suppression is inactive)
1564   if (((fCurrMajor & 0x1) == 0) && (mcmcount != mcmcountExp)) {
1565     LinkError(kMissMcmHeaders,
1566               "No. of MCM headers %i not as expected: %i",
1567               mcmcount, mcmcountExp);
1568   }
1569
1570   return (fPayloadCurr - start);
1571 }
1572
1573 Int_t AliTRDrawStream::ReadNonZSData()
1574 {
1575   // read the non-zs data from one link from the current reading position
1576
1577   UInt_t *start = fPayloadCurr;
1578
1579   Int_t mcmcount = 0;
1580   Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
1581   Int_t channelcount = 0;
1582   Int_t channelcountExp = 0;
1583   Int_t timebins;
1584   Int_t currentTimebin = 0;
1585   Int_t adcwc = 0;
1586   Int_t evno = -1;
1587   Int_t lastmcmpos = -1;
1588   Int_t lastrobpos = -1;
1589
1590   if (fCurrNtimebins != fNtimebins) {
1591     if (fNtimebins > 0)
1592       LinkError(kNtimebinsChanged,
1593                 "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
1594     fNtimebins = fCurrNtimebins;
1595   }
1596
1597   timebins = fNtimebins;
1598
1599   while (*(fPayloadCurr) != fgkDataEndmarker &&
1600          fPayloadCurr - fPayloadStart < fPayloadSize - 2) {
1601
1602     // ----- Checking MCM Header -----
1603     AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
1604
1605     // ----- checking for proper readout order - ROB -----
1606     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1607       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1608     }
1609     else {
1610       ROBError(kPosUnexp, Form("#%i after #%i in readout order", GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos));
1611     }
1612     fCurrRobPos = ROB(*fPayloadCurr);
1613
1614     // ----- checking for proper readout order - MCM -----
1615     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) >= (lastmcmpos + 1) % 16) {
1616       lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
1617     }
1618     else {
1619       MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
1620     }
1621     fCurrMcmPos = MCM(*fPayloadCurr);
1622
1623     if (EvNo(*fPayloadCurr) != evno) {
1624       if (evno == -1)
1625         evno = EvNo(*fPayloadCurr);
1626       else {
1627         MCMError(kPtrgCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
1628       }
1629     }
1630
1631     channelcount = 0;
1632     channelcountExp = 21;
1633     int channelno = -1;
1634
1635     Int_t adccoloff = AdcColOffset(*fPayloadCurr);
1636     Int_t padcoloff = PadColOffset(*fPayloadCurr);
1637     Int_t row = Row(*fPayloadCurr);
1638
1639     fPayloadCurr++;
1640
1641     // ----- reading marked ADC channels -----
1642     while (channelcount < channelcountExp &&
1643            *(fPayloadCurr) != fgkDataEndmarker) {
1644       if (channelno < 20)
1645         channelno++;
1646
1647       currentTimebin = 0;
1648
1649       adcwc = 0;
1650       Int_t nADCwords = (timebins + 2) / 3;
1651       AliDebug(2, Form("Now looking %i words", nADCwords));
1652       Int_t adccol = adccoloff - channelno;
1653       Int_t padcol = padcoloff - channelno;
1654       while ((adcwc < nADCwords) &&
1655              (*(fPayloadCurr) != fgkDataEndmarker) &&
1656              (fPayloadCurr - fPayloadStart < fPayloadSize)) {
1657         int check = 0x3 & *fPayloadCurr;
1658         if (channelno % 2 != 0) { // odd channel
1659           if (check != 0x2 && channelno < 21) {
1660             MCMError(kAdcCheckInvalid,
1661                      "%i for %2i. ADC word in odd channel %i",
1662                      check, adcwc+1, channelno);
1663           }
1664         }
1665         else {                  // even channel
1666           if (check != 0x3 && channelno < 21) {
1667             MCMError(kAdcCheckInvalid,
1668                      "%i for %2i. ADC word in even channel %i",
1669                      check, adcwc+1, channelno);
1670           }
1671         }
1672
1673         // filling the actual timebin data
1674         int tb2 = 0x3ff & *fPayloadCurr >> 22;
1675         int tb1 = 0x3ff & *fPayloadCurr >> 12;
1676         int tb0 = 0x3ff & *fPayloadCurr >> 2;
1677         if (adcwc != 0 || fCurrNtimebins <= 30)
1678           fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
1679         else
1680           tb0 = -1;
1681         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
1682         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
1683
1684         adcwc++;
1685         fPayloadCurr++;
1686       }
1687
1688       if (adcwc != nADCwords)
1689         MCMError(kAdcDataAbort);
1690
1691       // adding index
1692       if (padcol > 0 && padcol < 144) {
1693         fSignalIndex->AddIndexRC(row, padcol);
1694       }
1695
1696       channelcount++;
1697     }
1698
1699     if (channelcount != channelcountExp)
1700       MCMError(kAdcChannelsMiss);
1701     mcmcount++;
1702     // continue with next MCM
1703   }
1704
1705   // check for missing MCMs (if header suppression is inactive)
1706   if (mcmcount != mcmcountExp) {
1707     LinkError(kMissMcmHeaders,
1708               "%i not as expected: %i", mcmcount, mcmcountExp);
1709   }
1710
1711   return (fPayloadCurr - start);
1712 }
1713
1714 Int_t AliTRDrawStream::SeekNextLink()
1715 {
1716   // proceed in raw data stream till the next link
1717
1718   UInt_t *start = fPayloadCurr;
1719
1720   // read until data endmarkers
1721   while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1722          *fPayloadCurr != fgkDataEndmarker)
1723     fPayloadCurr++;
1724
1725   // read all data endmarkers
1726   while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1727          *fPayloadCurr == fgkDataEndmarker)
1728     fPayloadCurr++;
1729
1730   return (fPayloadCurr - start);
1731 }
1732
1733 Bool_t AliTRDrawStream::ConnectTracklets(TTree *trklTree)
1734 {
1735   // connect the tracklet tree used to store the tracklet output
1736
1737   fTrackletTree = trklTree;
1738   if (!fTrackletTree)
1739     return kTRUE;
1740
1741   if (!fTrackletTree->GetBranch("hc"))
1742     fTrackletTree->Branch("hc", &fCurrHC, "hc/I");
1743   else
1744     fTrackletTree->SetBranchAddress("hc", &fCurrHC);
1745
1746   if (!fTrackletTree->GetBranch("trkl"))
1747     fTrackletTree->Branch("trkl", &fTrackletArray);
1748   else
1749     fTrackletTree->SetBranchAddress("trkl", &fTrackletArray);
1750
1751   return kTRUE;
1752 }
1753
1754
1755 void AliTRDrawStream::EquipmentError(ErrorCode_t err, const char *const msg, ...)
1756 {
1757   // register error according to error code on equipment level
1758   // and return the corresponding error message
1759
1760   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
1761   fLastError.fStack  = -1;
1762   fLastError.fLink   = -1;
1763   fLastError.fRob    = -1;
1764   fLastError.fMcm    = -1;
1765   fLastError.fError  = err;
1766   (this->*fStoreError)();
1767
1768   va_list ap;
1769   if (fgErrorDebugLevel[err] > 10)
1770     AliDebug(fgErrorDebugLevel[err],
1771              Form("Event %6i: Eq. %2d - %s : %s",
1772                   fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
1773                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1774   else
1775     AliError(Form("Event %6i: Eq. %2d - %s : %s",
1776                   fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
1777                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1778   fErrorFlags |= fgErrorBehav[err];
1779 }
1780
1781
1782 void AliTRDrawStream::StackError(ErrorCode_t err, const char *const msg, ...)
1783 {
1784   // register error according to error code on stack level
1785   // and return the corresponding error message
1786
1787   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
1788   fLastError.fStack  = fCurrSlot;
1789   fLastError.fLink   = -1;
1790   fLastError.fRob    = -1;
1791   fLastError.fMcm    = -1;
1792   fLastError.fError  = err;
1793   (this->*fStoreError)();
1794
1795   va_list ap;
1796   if (fgErrorDebugLevel[err] > 0)
1797     AliDebug(fgErrorDebugLevel[err],
1798              Form("Event %6i: Eq. %2d S %i - %s : %s",
1799                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
1800                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1801   else
1802     AliError(Form("Event %6i: Eq. %2d S %i - %s : %s",
1803                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
1804                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1805   fErrorFlags |= fgErrorBehav[err];
1806 }
1807
1808
1809 void AliTRDrawStream::LinkError(ErrorCode_t err, const char *const msg, ...)
1810 {
1811   // register error according to error code on link level
1812   // and return the corresponding error message
1813
1814   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
1815   fLastError.fStack  = fCurrSlot;
1816   fLastError.fLink   = fCurrLink;
1817   fLastError.fRob    = -1;
1818   fLastError.fMcm    = -1;
1819   fLastError.fError  = err;
1820   (this->*fStoreError)();
1821
1822   va_list ap;
1823   if (fgErrorDebugLevel[err] > 0)
1824     AliDebug(fgErrorDebugLevel[err],
1825              Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
1826                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
1827                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1828   else
1829     AliError(Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
1830                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
1831                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1832   fErrorFlags |= fgErrorBehav[err];
1833 }
1834
1835
1836 void AliTRDrawStream::ROBError(ErrorCode_t err, const char *const msg, ...)
1837 {
1838   // register error according to error code on ROB level
1839   // and return the corresponding error message
1840
1841   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
1842   fLastError.fStack  = fCurrSlot;
1843   fLastError.fLink   = fCurrLink;
1844   fLastError.fRob    = fCurrRobPos;
1845   fLastError.fMcm    = -1;
1846   fLastError.fError  = err;
1847   (this->*fStoreError)();
1848
1849   va_list ap;
1850   if (fgErrorDebugLevel[err] > 0)
1851     AliDebug(fgErrorDebugLevel[err],
1852              Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
1853                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
1854                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1855   else
1856     AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
1857                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
1858                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1859   fErrorFlags |= fgErrorBehav[err];
1860 }
1861
1862
1863 void AliTRDrawStream::MCMError(ErrorCode_t err, const char *const msg, ...)
1864 {
1865   // register error according to error code on MCM level
1866   // and return the corresponding error message
1867
1868   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
1869   fLastError.fStack  = fCurrSlot;
1870   fLastError.fLink   = fCurrLink;
1871   fLastError.fRob    = fCurrRobPos;
1872   fLastError.fMcm    = fCurrMcmPos;
1873   fLastError.fError  = err;
1874   (this->*fStoreError)();
1875
1876   va_list ap;
1877   if (fgErrorDebugLevel[err] > 0)
1878     AliDebug(fgErrorDebugLevel[err],
1879              Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
1880                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
1881                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1882   else
1883     AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
1884                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
1885                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1886   fErrorFlags |= fgErrorBehav[err];
1887 }
1888
1889 const char* AliTRDrawStream::GetErrorMessage(ErrorCode_t errCode)
1890 {
1891   // return the error message for the given error code
1892
1893   if (errCode > 0 && errCode < kLastErrorCode)
1894     return fgkErrorMessages[errCode];
1895   else
1896     return "";
1897 }
1898
1899 void AliTRDrawStream::AliTRDrawStats::ClearStats()
1900 {
1901   // clear statistics (includes clearing sector-wise statistics)
1902
1903   fBytesRead = 0;
1904   for (Int_t iSector = 0; iSector < 18; iSector++) {
1905     fStatsSector[iSector].ClearStats();
1906   }
1907
1908 }
1909
1910 void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::ClearStats()
1911 {
1912   // clear statistics (includes clearing HC-wise statistics)
1913
1914   fBytes = 0;
1915   fBytesRead = 0;
1916   fNTracklets = 0;
1917   fNMCMs = 0;
1918   fNChannels = 0;
1919
1920   for (Int_t iHC = 0; iHC < 60; iHC++) {
1921     fStatsHC[iHC].ClearStats();
1922   }
1923 }
1924
1925 void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::AliTRDrawStatsHC::ClearStats()
1926 {
1927   // clear statistics
1928
1929   fBytes = 0;
1930   fBytesRead = 0;
1931   fNTracklets = 0;
1932   fNMCMs = 0;
1933   fNChannels = 0;
1934 }
1935
1936 void AliTRDrawStream::SetDumpMCM(Int_t det, Int_t rob, Int_t mcm, Bool_t dump)
1937 {
1938   // mark MCM for dumping of raw data
1939
1940   if (dump) {
1941     fDumpMCM[fNDumpMCMs++] = (det << 7) | (rob << 4) | mcm;
1942   }
1943   else {
1944     Int_t iMCM;
1945     for (iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
1946       if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
1947         fNDumpMCMs--;
1948         break;
1949       }
1950     }
1951     for ( ; iMCM < fNDumpMCMs; iMCM++) {
1952       fDumpMCM[iMCM] = fDumpMCM[iMCM+1];
1953     }
1954   }
1955 }
1956
1957 Bool_t AliTRDrawStream::DumpingMCM(Int_t det, Int_t rob, Int_t mcm)  const
1958 {
1959   // check if MCM data should be dumped
1960
1961   for (Int_t iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
1962     if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
1963       return kTRUE;
1964     }
1965   }
1966   return kFALSE;
1967 }
1968
1969 TString AliTRDrawStream::DumpRaw(TString title, UInt_t *start, Int_t length, UInt_t endmarker)
1970 {
1971   // dump raw data
1972
1973   title += "\n";
1974   for (Int_t pos = 0; pos < length; pos += 4) {
1975     if ((start[pos+0] != endmarker) && pos+0 < length)
1976       if ((start[pos+1] != endmarker && pos+1 < length))
1977         if ((start[pos+2] != endmarker && pos+2 < length))
1978           if ((start[pos+3] != endmarker && pos+3 < length))
1979             title += Form("   0x%08x 0x%08x 0x%08x 0x%08x\n",
1980                           start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
1981           else {
1982             title += Form("   0x%08x 0x%08x 0x%08x 0x%08x\n",
1983                           start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
1984             return title;
1985           }
1986         else {
1987           title += Form("   0x%08x 0x%08x 0x%08x\n",
1988                         start[pos+0], start[pos+1], start[pos+2]);
1989           return title;
1990         }
1991       else {
1992         title += Form("   0x%08x 0x%08x\n",
1993                       start[pos+0], start[pos+1]);
1994         return title;
1995       }
1996     else {
1997       title += Form("   0x%08x\n",
1998                     start[pos+0]);
1999       return title;
2000     }
2001   }
2002   return title;
2003 }
2004
2005 TString AliTRDrawStream::DumpMcmHeader(TString title, UInt_t word)
2006 {
2007   title += Form("0x%08x -> ROB: %i, MCM: %2i",
2008                 word, ROB(word), MCM(word));
2009   return title;
2010 }
2011
2012 TString AliTRDrawStream::DumpAdcMask(TString title, UInt_t word)
2013 {
2014   title += Form("0x%08x -> #ch : %2i, 0x%06x (%2i ch)",
2015                 word, GetNActiveChannels(word), GetActiveChannels(word), GetNActiveChannelsFromMask(word));
2016   return title;
2017 }
2018
2019 AliTRDrawStream::AliTRDrawStreamError::AliTRDrawStreamError(Int_t error, Int_t sector, Int_t stack, Int_t link, Int_t rob, Int_t mcm) :
2020   fError(error),
2021   fSector(sector),
2022   fStack(stack),
2023   fLink(link),
2024   fRob(rob),
2025   fMcm(mcm)
2026 {
2027   // ctor
2028
2029 }