LCOV - code coverage report
Current view: top level - TRD/TRDbase - AliTRDrawStream.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 530 1285 41.2 %
Date: 2016-06-14 17:26:59 Functions: 22 43 51.2 %

          Line data    Source code
       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             : //  CRC checks rely on boost, and are enabled only when TRD_RAW_CRC       //
      22             : //  is defined                                                            //
      23             : //                                                                        //
      24             : //  Additional debug features can be enabled by defining TRD_RAW_DEBUG    //
      25             : //                                                                        //
      26             : //  Author: J. Klein (jochen.klein@cern.ch)                               //
      27             : //                                                                        //
      28             : ////////////////////////////////////////////////////////////////////////////
      29             : 
      30             : #include <cstdio>
      31             : #include <cstdarg>
      32             : 
      33             : #if defined(TRD_RAW_CRC)
      34             : #include <boost/crc.hpp>
      35             : #endif
      36             : 
      37             : #include "TClonesArray.h"
      38             : #include "TTree.h"
      39             : 
      40             : #include "AliLog.h"
      41             : #include "AliRawReader.h"
      42             : #include "AliTRDcalibDB.h"
      43             : #include "AliTRDdigitsManager.h"
      44             : #include "AliTRDdigitsParam.h"
      45             : #include "AliTRDcalibDB.h"
      46             : #include "AliTRDmcmSim.h"
      47             : #include "AliTRDtrapConfig.h"
      48             : #include "AliTRDarrayADC.h"
      49             : #include "AliTRDarrayDictionary.h"
      50             : #include "AliTRDSignalIndex.h"
      51             : #include "AliTRDtrackletWord.h"
      52             : #include "AliTRDtrackletMCM.h"
      53             : #include "AliESDTrdTrack.h"
      54             : 
      55             : #include "AliTRDrawStream.h"
      56             : 
      57          48 : ClassImp(AliTRDrawStream)
      58             : 
      59             : // some static information
      60             : Int_t AliTRDrawStream::fgMcmOrder[] = {12, 13, 14, 15,
      61             :                                        8, 9, 10, 11,
      62             :                                        4, 5, 6, 7,
      63             :                                        0, 1, 2, 3};
      64             : Int_t  AliTRDrawStream::fgRobOrder [] = {0, 1, 2, 3};
      65             : const Int_t  AliTRDrawStream::fgkNlinks = 12;
      66             : const Int_t  AliTRDrawStream::fgkNstacks = 5;
      67             : const Int_t  AliTRDrawStream::fgkNsectors = 18;
      68             : const Int_t  AliTRDrawStream::fgkNtriggers = 12;
      69             : const UInt_t AliTRDrawStream::fgkDataEndmarker     = 0x00000000;
      70             : const UInt_t AliTRDrawStream::fgkTrackletEndmarker = 0x10001000;
      71             : const UInt_t AliTRDrawStream::fgkStackEndmarker[] = { 0xe0d01000, 0xe0d10000 };
      72             : 
      73             : const char* AliTRDrawStream::fgkErrorMessages[] = {
      74             :   "Unknown error",
      75             :   "Link monitor active",
      76             :   "Event counter mismatch",
      77             :   "not a TRD equipment (1024-1041)",
      78             :   "Invalid Stack header",
      79             :   "Invalid detector number",
      80             :   "Invalid pad row",
      81             :   "No digits could be retrieved from the digitsmanager",
      82             :   "HC header mismatch",
      83             :   "HC check bits wrong",
      84             :   "Unexpected position in readout stream",
      85             :   "Invalid testpattern mode",
      86             :   "Testpattern mismatch",
      87             :   "Number of timebins changed",
      88             :   "ADC mask inconsistent",
      89             :   "ADC check bits invalid",
      90             :   "Missing ADC data",
      91             :   "Missing expected ADC channels",
      92             :   "Missing MCM headers",
      93             :   "Missing TP data",
      94             :   "CRC mismatch"
      95             : };
      96             : 
      97             : Int_t AliTRDrawStream::fgErrorDebugLevel[] = {
      98             :   0,
      99             :   0,
     100             :   2,
     101             :   1,
     102             :   0,
     103             :   1,
     104             :   0,
     105             :   1,
     106             :   0,
     107             :   1,
     108             :   2,
     109             :   1,
     110             :   0,
     111             :   1,
     112             :   1,
     113             :   2,
     114             :   1,
     115             :   1,
     116             :   1,
     117             :   0,
     118             :   0
     119             : };
     120             : 
     121             : AliTRDrawStream::ErrorBehav_t AliTRDrawStream::fgErrorBehav[] = {
     122             :   AliTRDrawStream::kTolerate,
     123             :   AliTRDrawStream::kDiscardHC,
     124             :   AliTRDrawStream::kTolerate,
     125             :   AliTRDrawStream::kAbort,
     126             :   AliTRDrawStream::kAbort,
     127             :   AliTRDrawStream::kAbort,
     128             :   AliTRDrawStream::kDiscardMCM,
     129             :   AliTRDrawStream::kAbort,
     130             :   AliTRDrawStream::kDiscardHC,
     131             :   AliTRDrawStream::kDiscardHC,
     132             :   AliTRDrawStream::kTolerate,
     133             :   AliTRDrawStream::kTolerate,
     134             :   AliTRDrawStream::kTolerate,
     135             :   AliTRDrawStream::kTolerate,
     136             :   AliTRDrawStream::kTolerate,
     137             :   AliTRDrawStream::kTolerate,
     138             :   AliTRDrawStream::kTolerate,
     139             :   AliTRDrawStream::kTolerate,
     140             :   AliTRDrawStream::kTolerate,
     141             :   AliTRDrawStream::kTolerate,
     142             :   AliTRDrawStream::kTolerate
     143             : };
     144             : 
     145           2 : AliTRDrawStream::AliTRDrawStream(AliRawReader *rawReader) :
     146           2 :   fStoreError(&AliTRDrawStream::ForgetError),
     147           2 :   fRawReader(rawReader),
     148           2 :   fDigitsManager(0x0),
     149           2 :   fDigitsParam(0x0),
     150           2 :   fErrors(0x0),
     151           2 :   fLastError(),
     152           2 :   fErrorFlags(0),
     153           2 :   fStats(),
     154           2 :   fPayloadStart(0x0),
     155           2 :   fPayloadCurr(0x0),
     156           2 :   fPayloadSize(0),
     157           2 :   fNtimebins(-1),
     158           2 :   fLastEvId(-1),
     159           2 :   fCurrSlot(-1),
     160           2 :   fCurrLink(-1),
     161           2 :   fCurrRobPos(-1),
     162           2 :   fCurrMcmPos(-1),
     163           2 :   fCurrEquipmentId(0),
     164           2 :   fCurrSmHeaderSize(0),
     165           2 :   fCurrSmHeaderVersion(0),
     166           2 :   fCurrTrailerReadout(0),
     167           2 :   fCurrTrgHeaderAvail(0),
     168           2 :   fCurrTrgHeaderReadout(0),
     169           2 :   fCurrTrkHeaderAvail(0),
     170           2 :   fCurrStackEndmarkerAvail(0),
     171           2 :   fCurrEvType(0),
     172           2 :   fCurrTriggerEnable(0),
     173           2 :   fCurrTriggerFired(0),
     174           2 :   fCurrTrackEnable(0),
     175           2 :   fCurrTrackletEnable(0),
     176           2 :   fCurrStackMask(0),
     177             : #ifdef TRD_RAW_DEBUG
     178             :   fCurrL0Count(),
     179             :   fCurrL1aCount(),
     180             :   fCurrL1rCount(),
     181             :   fCurrL2aCount(),
     182             :   fCurrL2rCount(),
     183             :   fCurrL0offset(),
     184             : #endif
     185           2 :   fCurrTrkHeaderIndexWord(0x0),
     186           2 :   fCurrTrkHeaderSize(0x0),
     187           2 :   fCurrTrkFlags(0x0),
     188           2 :   fCurrTrgHeaderIndexWord(0x0),
     189           2 :   fCurrTrgHeaderSize(0x0),
     190           2 :   fCurrTrgFlags(0x0),
     191           2 :   fCurrStackIndexWord(0x0),
     192           2 :   fCurrStackHeaderSize(0x0),
     193           2 :   fCurrStackHeaderVersion(0x0),
     194           2 :   fCurrLinkMask(0x0),
     195           2 :   fCurrCleanCheckout(0x0),
     196           2 :   fCurrBoardId(0x0),
     197           2 :   fCurrHwRev(-1),
     198           2 :   fCurrHwRevTMU(0x0),
     199           2 :   fCurrLinkMonitorFlags(0x0),
     200           2 :   fCurrLinkDataTypeFlags(0x0),
     201           2 :   fCurrLinkDebugFlags(0x0),
     202           2 :   fCurrMatchFlagsSRAM(),
     203           2 :   fCurrMatchFlagsPostBP(),
     204           2 :   fCurrChecksumStack(),
     205           2 :   fCurrChecksumSIU(0),
     206           2 :   fCurrSpecial(-1),
     207           2 :   fCurrMajor(-1),
     208           2 :   fCurrMinor(-1),
     209           2 :   fCurrAddHcWords(-1),
     210           2 :   fCurrSm(-1),
     211           2 :   fCurrStack(-1),
     212           2 :   fCurrLayer(-1),
     213           2 :   fCurrSide(-1),
     214           2 :   fCurrHC(-1),
     215           2 :   fCurrCheck(-1),
     216           2 :   fCurrNtimebins(-1),
     217           2 :   fCurrPtrgCnt(-1),
     218           2 :   fCurrPtrgPhase(-1),
     219             : #ifdef TRD_RAW_DEBUG
     220             :   fCurrBC(),
     221             : #endif
     222           2 :   fNDumpMCMs(0),
     223           2 :   fAdcArray(0x0),
     224           2 :   fSignalIndex(0x0),
     225           2 :   fTracklets(0x0),
     226           2 :   fTracks(0x0),
     227           2 :   fMarkers(0x0)
     228          10 : {
     229             :   // default constructor
     230             : 
     231           4 :   fCurrTrkHeaderIndexWord = new UInt_t[fgkNstacks];
     232           4 :   fCurrTrkHeaderSize      = new UInt_t[fgkNstacks];
     233           4 :   fCurrTrkFlags           = new ULong64_t[fgkNsectors*fgkNstacks];
     234           4 :   fCurrTrgHeaderIndexWord = new UInt_t[fgkNtriggers];
     235           4 :   fCurrTrgHeaderSize      = new UInt_t[fgkNtriggers];
     236           4 :   fCurrTrgFlags           = new UInt_t[fgkNsectors];
     237             : #ifdef TRD_RAW_DEBUG
     238             :   fCurrL0Count            = new UInt_t[fgkNsectors];
     239             :   fCurrL1aCount           = new UInt_t[fgkNsectors];
     240             :   fCurrL1rCount           = new UInt_t[fgkNsectors];
     241             :   fCurrL2aCount           = new UInt_t[fgkNsectors];
     242             :   fCurrL2rCount           = new UInt_t[fgkNsectors];
     243             : #endif
     244           4 :   fCurrStackIndexWord     = new UInt_t[fgkNstacks];
     245           4 :   fCurrStackHeaderSize    = new UInt_t[fgkNstacks];
     246           4 :   fCurrStackHeaderVersion = new UInt_t[fgkNstacks];
     247           4 :   fCurrLinkMask           = new UInt_t[fgkNstacks];
     248           4 :   fCurrCleanCheckout      = new UInt_t[fgkNstacks];
     249           4 :   fCurrBoardId            = new UInt_t[fgkNstacks];
     250           4 :   fCurrHwRevTMU           = new UInt_t[fgkNstacks];
     251           4 :   fCurrLinkMonitorFlags   = new UInt_t[fgkNsectors * fgkNstacks * fgkNlinks];
     252           4 :   fCurrLinkDataTypeFlags  = new UInt_t[fgkNstacks * fgkNlinks];
     253           4 :   fCurrLinkDebugFlags     = new UInt_t[fgkNstacks * fgkNlinks];
     254          76 :   for (Int_t iSector = 0; iSector < fgkNsectors; iSector++)
     255          36 :     fCurrTrgFlags[iSector] = 0;
     256         404 :   for (Int_t i = 0; i < 100; i++)
     257         200 :     fDumpMCM[i] = 0;
     258             : 
     259             :   // setting up the error tree
     260           6 :   fErrors = new TTree("errorStats", "Error statistics");
     261           2 :   fErrors->SetDirectory(0x0);
     262           2 :   fErrors->Branch("error", &fLastError);
     263           2 :   fErrors->SetCircular(1000);
     264         404 :   for (Int_t i = 0; i < 100; i++) {
     265         200 :     fErrorBuffer[i] = 0;
     266             :   }
     267             : 
     268           4 : }
     269             : 
     270             : AliTRDrawStream::~AliTRDrawStream()
     271          12 : {
     272             :   // destructor
     273             : 
     274           4 :   delete fErrors;
     275             : 
     276           4 :   delete [] fCurrTrkHeaderIndexWord;
     277           4 :   delete [] fCurrTrkHeaderSize;
     278           4 :   delete [] fCurrTrkFlags;
     279           4 :   delete [] fCurrTrgHeaderIndexWord;
     280           4 :   delete [] fCurrTrgHeaderSize;
     281           4 :   delete [] fCurrTrgFlags;
     282           4 :   delete [] fCurrStackIndexWord;
     283           4 :   delete [] fCurrStackHeaderSize;
     284           4 :   delete [] fCurrStackHeaderVersion;
     285           4 :   delete [] fCurrLinkMask;
     286           4 :   delete [] fCurrCleanCheckout;
     287           4 :   delete [] fCurrBoardId;
     288           4 :   delete [] fCurrHwRevTMU;
     289           4 :   delete [] fCurrLinkMonitorFlags;
     290           4 :   delete [] fCurrLinkDataTypeFlags;
     291           4 :   delete [] fCurrLinkDebugFlags;
     292           6 : }
     293             : 
     294             : Bool_t AliTRDrawStream::ReadEvent()
     295             : {
     296             :   // read the current event from the raw reader and fill it to the digits manager
     297             : 
     298           0 :   if (!fRawReader) {
     299           0 :     AliError("No raw reader available");
     300           0 :     return kFALSE;
     301             :   }
     302             : 
     303             :   // some preparations
     304           0 :   fDigitsParam = 0x0;
     305             : 
     306             :   // loop over all DDLs
     307             :   // data starts with GTU payload, i.e. SM index word
     308           0 :   UChar_t *buffer = 0x0;
     309             : 
     310           0 :   while (fRawReader->ReadNextData(buffer)) {
     311             : 
     312           0 :     fCurrEquipmentId = fRawReader->GetEquipmentId();
     313           0 :     AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
     314             : 
     315           0 :     if (fCurrEquipmentId < kDDLOffset || fCurrEquipmentId > kDDLMax) {
     316           0 :       EquipmentError(kNonTrdEq, "Skipping");
     317           0 :       continue;
     318             :     }
     319             : 
     320           0 :     if (fMarkers)
     321           0 :       new ((*fMarkers)[fMarkers->GetEntriesFast()])
     322           0 :         AliTRDrawStreamError(-kSecactive, fCurrEquipmentId - kDDLOffset);
     323             : 
     324           0 :     ReadGTUHeaders((UInt_t*) buffer);
     325             : 
     326           0 :     if (fCurrTrailerReadout)
     327           0 :       ReadGTUTrailer();
     328             : 
     329             : #ifdef TRD_RAW_CRC
     330             :     boost::crc_optimal<16, 0x8005, 0, 0, false, false>      checksumStack[5];
     331             :     boost::crc_optimal<32, 0x04C11DB7, 0, 0, false, false>  checksumSIU;
     332             :     checksumSIU.reset();
     333             : 
     334             :     // process CDH, replace size with 0xffffffff
     335             :     UInt_t temp = 0xffffffff;
     336             :     checksumSIU.process_bytes(&temp, sizeof(UInt_t));
     337             :     UInt_t *data = (UInt_t*) fRawReader->GetDataHeader();
     338             :     checksumSIU.process_bytes(&data[1], 7*sizeof(UInt_t));
     339             :     // process payload including everything but the SIU checksum
     340             :     checksumSIU.process_bytes(buffer, fRawReader->GetDataSize()-4);
     341             : 
     342             :     if (checksumSIU() != fCurrChecksumSIU) {
     343             :       EquipmentError(kCRCmismatch, "SIU data - recalc: 0x%08x - 0x%08x", fCurrChecksumSIU, checksumSIU());
     344             :     }
     345             : #endif
     346             : 
     347             :     // loop over all active links
     348           0 :     AliDebug(2, Form("Stack mask 0x%02x", fCurrStackMask));
     349           0 :     for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
     350           0 :       fCurrSlot = iStack;
     351             : #ifdef TRD_RAW_CRC
     352             :       checksumStack[iStack].reset();
     353             : #endif
     354             : 
     355           0 :       if ((fCurrStackMask & (1 << fCurrSlot)) == 0)
     356             :         continue;
     357             : 
     358           0 :       AliDebug(2, Form("Stack %i, Link mask: 0x%02x", fCurrSlot, fCurrLinkMask[fCurrSlot]));
     359           0 :       for (Int_t iLink = 0; iLink < fgkNlinks; iLink++) {
     360           0 :         fCurrLink = iLink;
     361           0 :         fCurrHC   = (fCurrEquipmentId - kDDLOffset) * fgkNstacks * fgkNlinks +
     362           0 :           fCurrSlot * fgkNlinks + iLink;
     363           0 :         if ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) == 0)
     364             :           continue;
     365             : 
     366             : #ifdef TRD_RAW_CRC
     367             :         UInt_t *start = fPayloadCurr;
     368             : #endif
     369             :         Int_t   size  = 0;
     370             : 
     371           0 :         fErrorFlags = 0;
     372             :         // check for link monitor error flag
     373           0 :         if (fCurrLinkMonitorFlags[(((fCurrEquipmentId - kDDLOffset) * fgkNstacks) + fCurrSlot) * fgkNlinks + fCurrLink] != 0) {
     374           0 :           LinkError(kLinkMonitor);
     375           0 :           if (fgErrorBehav[kLinkMonitor] == kTolerate)
     376           0 :             size += ReadLinkData();
     377             :         }
     378             :         else
     379             :           // read the data from one HC
     380           0 :           size += ReadLinkData();
     381             : 
     382             :         // read all data endmarkers
     383           0 :         size += SeekNextLink();
     384             : 
     385             : #ifdef TRD_RAW_CRC
     386             :         // always use data for CRC calculation
     387             :         // (even if link monitor active)
     388             :         UShort_t crc = CalcLinkChecksum(start, size);
     389             :         checksumStack[iStack].process_bytes(&crc, sizeof(UShort_t));
     390             : #endif
     391           0 :       }
     392             : #ifdef TRD_RAW_CRC
     393             :       if (fDigitsManager && (checksumStack[iStack]() != fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][iStack])) {
     394             :         StackError(kCRCmismatch, "data - recalc: 0x%04x - 0x%04x", fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][iStack], checksumStack[iStack]());
     395             :       }
     396             : #endif
     397             : 
     398             :       // continue with next stack
     399           0 :       SeekNextStack();
     400           0 :     }
     401             :   }
     402             : 
     403             :   return kTRUE;
     404           0 : }
     405             : 
     406             : 
     407             : Bool_t AliTRDrawStream::NextDDL()
     408             : {
     409             :   // continue reading with the next equipment
     410             : 
     411         152 :   if (!fRawReader)
     412           0 :     return kFALSE;
     413             : 
     414          76 :   fCurrEquipmentId = 0;
     415          76 :   fCurrSlot = 0;
     416          76 :   fCurrLink = 0;
     417             : 
     418          76 :   UChar_t *buffer = 0x0;
     419             : 
     420         152 :   while (fRawReader->ReadNextData(buffer)) {
     421             : 
     422          72 :     fCurrEquipmentId = fRawReader->GetEquipmentId();
     423         216 :     AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
     424             : 
     425         144 :     if (fCurrEquipmentId < kDDLOffset || fCurrEquipmentId > kDDLMax) {
     426           0 :       EquipmentError(kNonTrdEq, "Skipping");
     427           0 :       continue;
     428             :     }
     429             : 
     430          72 :     if (fMarkers)
     431           0 :       new ((*fMarkers)[fMarkers->GetEntriesFast()])
     432           0 :         AliTRDrawStreamError(-kSecactive, fCurrEquipmentId - kDDLOffset);
     433             : 
     434          72 :     ReadGTUHeaders((UInt_t*) buffer);
     435             : 
     436          72 :     if (fCurrTrailerReadout)
     437           0 :       ReadGTUTrailer();
     438             : 
     439          72 :     return kTRUE;
     440             :   }
     441             : 
     442           4 :   return kFALSE;
     443         152 : }
     444             : 
     445             : 
     446             : Int_t AliTRDrawStream::NextChamber(AliTRDdigitsManager *digMgr)
     447             : {
     448             :   // read the data for the next chamber
     449             :   // in case you only want to read the data of a single chamber
     450             :   // to read all data ReadEvent(...) is recommended
     451             : 
     452        4328 :   fDigitsManager = digMgr;
     453        2164 :   fDigitsParam   = 0x0;
     454             : 
     455        2164 :   fErrorFlags = 0;
     456             : 
     457        2164 :   if (!fRawReader) {
     458           0 :     AliError("No raw reader available");
     459           0 :     return -1;
     460             :   }
     461             : 
     462        4468 :   while (fCurrSlot < 0 || fCurrSlot >= fgkNstacks) {
     463          76 :     if (!NextDDL()) {
     464           4 :       fCurrSlot = -1;
     465           4 :       return -1;
     466             :     }
     467         144 :     while ((fCurrSlot < fgkNstacks) &&
     468          72 :            (((fCurrStackMask & (1 << fCurrSlot)) == 0) ||
     469          72 :             ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0)) {
     470           0 :       if ((fCurrStackMask & (1 << fCurrSlot)) == 0) {
     471           0 :         ++fCurrSlot;
     472           0 :         fCurrLink = 0;
     473           0 :         continue;
     474             :       }
     475           0 :       fCurrLink++;
     476           0 :       if (fCurrLink >= fgkNlinks) {
     477           0 :         SeekNextStack();
     478           0 :         fCurrLink = 0;
     479           0 :         fCurrSlot++;
     480           0 :       }
     481             :     }
     482             :   }
     483             : 
     484        6480 :   AliDebug(2, Form("Stack %i, Link %i, mask: 0x%02x", fCurrSlot, fCurrLink, fCurrLinkMask[fCurrSlot]));
     485        6480 :   fCurrHC   = (fCurrEquipmentId - kDDLOffset) * fgkNlinks * fgkNstacks +
     486        4320 :     fCurrSlot * fgkNlinks + fCurrLink;
     487             : 
     488        2160 :   if (fCurrLinkMonitorFlags[(((fCurrEquipmentId - kDDLOffset) * fgkNstacks) + fCurrSlot) * fgkNlinks + fCurrLink] != 0) {
     489           0 :     LinkError(kLinkMonitor);
     490           0 :     if (fgErrorBehav[kLinkMonitor] == kTolerate)
     491           0 :       ReadLinkData();
     492             :   }
     493             :   else
     494             :     // read the data from one HC
     495        2160 :     ReadLinkData();
     496             : 
     497             :   // read all data endmarkers
     498        2160 :   SeekNextLink();
     499             : 
     500        2160 :   if (fCurrLink % 2 == 0) {
     501             :     // if we just read the A-side HC then also check the B-side
     502        2160 :     fCurrLink++;
     503        2160 :     fCurrHC++;
     504        2160 :     if (fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) {
     505        2160 :       if (fCurrLinkMonitorFlags[(((fCurrEquipmentId - kDDLOffset) * fgkNstacks) + fCurrSlot) * fgkNlinks + fCurrLink] != 0) {
     506           0 :         LinkError(kLinkMonitor);
     507           0 :         if (fgErrorBehav[kLinkMonitor] == kTolerate)
     508           0 :           ReadLinkData();
     509             :       }
     510             :       else {
     511        2160 :         ReadLinkData();
     512             :       }
     513        2160 :       SeekNextLink();
     514        2160 :     }
     515             :   }
     516             : 
     517             :   do {
     518        2160 :     if ((fCurrStackMask & (1 << fCurrSlot)) == 0) {
     519           0 :       fCurrLink = 0;
     520           0 :       fCurrSlot++;
     521           0 :     }
     522             :     else {
     523        2160 :       fCurrLink++;
     524        2160 :       if (fCurrLink >= fgkNlinks) {
     525         360 :         SeekNextStack();
     526         360 :         fCurrLink = 0;
     527         360 :         fCurrSlot++;
     528         360 :       }
     529             :     }
     530        4248 :   } while ((fCurrSlot < fgkNstacks) &&
     531        2088 :            (((fCurrStackMask & (1 << fCurrSlot)) == 0) ||
     532        2088 :             ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0));
     533             : 
     534             :   // return chamber information from HC if it is valid
     535             :   // otherwise return information from link position
     536       12960 :   if (fCurrSm < 0 || fCurrSm >= fgkNsectors || fCurrStack < 0 || fCurrStack >= fgkNstacks || fCurrLayer < 0 || fCurrLayer >= fgkNlinks/2)
     537           0 :     return ((fCurrEquipmentId-kDDLOffset) + fCurrSlot * fgkNlinks/2 + fCurrLink/2);
     538             :   else
     539        2160 :     return (fCurrSm * fgkNstacks*fgkNlinks/2 + fCurrStack * fgkNlinks/2 + fCurrLayer);
     540        2164 : }
     541             : 
     542             : 
     543             : Int_t AliTRDrawStream::ReadGTUHeaders(UInt_t *buffer)
     544             : {
     545             :   // check the data source and read the headers
     546             : 
     547         216 :   if (fCurrEquipmentId >= kDDLOffset && fCurrEquipmentId <= kDDLMax) {
     548             :     // this is ROC data
     549             : 
     550             :     // setting the pointer to data and current reading position
     551          72 :     fPayloadCurr = fPayloadStart = buffer;
     552          72 :     fPayloadSize = fRawReader->GetDataSize() / sizeof(UInt_t);
     553          72 :     fStats.fStatsSector[fCurrEquipmentId - kDDLOffset].fBytes = fRawReader->GetDataSize();
     554         216 :     AliDebug(2, Form("Read buffer of size: %i", fRawReader->GetDataSize()));
     555             : 
     556         216 :     AliDebug(1, DumpRaw("raw data", fPayloadCurr, TMath::Min(fPayloadSize, 1000)));
     557             : 
     558             :     // read SM header
     559          72 :     if (ReadSmHeader() < 0) {
     560           0 :       AliError(Form("Reading SM header failed, skipping this DDL %i", fCurrEquipmentId));
     561           0 :       return -1;
     562             :     }
     563             : 
     564             :     // read tracking headers (if available)
     565          72 :     if (fCurrTrkHeaderAvail) {
     566           0 :       for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
     567           0 :         if ((fCurrStackMask & (1 << iStack)) != 0)
     568           0 :           ReadTrackingHeader(iStack);
     569             :       }
     570           0 :     }
     571             : 
     572             :     // read trigger header(s) (if available)
     573          72 :     if (fCurrTrgHeaderAvail)
     574           0 :       ReadTriggerHeaders();
     575             : 
     576             :     // read stack header
     577         864 :     for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
     578         360 :       if ((fCurrStackMask & (1 << iStack)) != 0)
     579         360 :         ReadStackHeader(iStack);
     580             :     }
     581             : 
     582          72 :     return 0;
     583             :   }
     584             :   else
     585           0 :     return -1;
     586          72 : }
     587             : 
     588             : Int_t AliTRDrawStream::ReadSmHeader()
     589             : {
     590             :   // read the SMU index header at the current reading position
     591             :   // and store the information in the corresponding variables
     592             : 
     593         144 :   if (fPayloadCurr - fPayloadStart >= fPayloadSize - 1) {
     594           0 :     EquipmentError(kUnknown, "SM Header incomplete");
     595           0 :     return -1;
     596             :   }
     597             : 
     598          72 :   fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] = 0;
     599             : 
     600          72 :   fCurrSmHeaderSize           = ((*fPayloadCurr) >> 16) & 0xffff;
     601          72 :   fCurrSmHeaderVersion        = ((*fPayloadCurr) >> 12) &    0xf;
     602          72 :   fCurrTrackEnable            = ((*fPayloadCurr) >>  6) &    0x1;
     603          72 :   fCurrTrackletEnable         = ((*fPayloadCurr) >>  5) &    0x1;
     604          72 :   fCurrStackMask              = ((*fPayloadCurr)      ) &   0x1f;
     605          72 :   fCurrHwRev                  = (fPayloadCurr[1] >> 12) & 0xffff;
     606          72 :   fCurrStackEndmarkerAvail    = 0;
     607             : 
     608          72 :   switch (fCurrSmHeaderVersion) {
     609             :   case 0xb:
     610          72 :     fCurrTrailerReadout = 0;
     611          72 :     fCurrTrgHeaderAvail = 0;
     612          72 :     fCurrEvType = 0;
     613          72 :     fCurrTrkHeaderAvail = 0;
     614             : 
     615          72 :     DecodeGTUtracks();
     616          72 :     break;
     617             : 
     618             :   case 0xc:
     619           0 :     fCurrTrailerReadout = ((*fPayloadCurr) >> 10) &    0x1;
     620           0 :     fCurrTrgHeaderAvail = 1;
     621           0 :     fCurrTrgHeaderReadout = ((*fPayloadCurr) >>  9) &    0x1;
     622           0 :     fCurrEvType         = ((*fPayloadCurr) >>  7) &    0x3;
     623           0 :     fCurrTrkHeaderAvail = fCurrTrackEnable;
     624           0 :     fCurrTriggerEnable  = (fPayloadCurr[2] >>  8) &  0xfff;
     625           0 :     fCurrTriggerFired   = (fPayloadCurr[2] >>  20) &  0xfff;
     626           0 :     fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] = fCurrTriggerFired;
     627           0 :     break;
     628             : 
     629             :   case 0xd:
     630           0 :     fCurrTrailerReadout = ((*fPayloadCurr) >> 10) &    0x1;
     631           0 :     fCurrTrgHeaderAvail = 1;
     632           0 :     fCurrTrgHeaderReadout = ((*fPayloadCurr) >>  9) &    0x1;
     633           0 :     fCurrEvType         = ((*fPayloadCurr) >>  7) &    0x3;
     634           0 :     fCurrTrkHeaderAvail = fCurrTrackEnable;
     635           0 :     fCurrTriggerEnable  = (fPayloadCurr[2] >>  8) &  0xfff;
     636           0 :     fCurrTriggerFired   = (fPayloadCurr[2] >>  20) &  0xfff;
     637           0 :     fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] = fCurrTriggerFired;
     638           0 :     fCurrStackEndmarkerAvail    = 1;
     639             : #ifdef TRD_RAW_DEBUG
     640             :     if (fCurrSmHeaderSize > 7) {
     641             :       fCurrL0Count[fCurrEquipmentId-kDDLOffset]  = fPayloadCurr[3];
     642             :       fCurrL1aCount[fCurrEquipmentId-kDDLOffset] = fPayloadCurr[4];
     643             :       fCurrL1rCount[fCurrEquipmentId-kDDLOffset] = fPayloadCurr[5];
     644             :       fCurrL2aCount[fCurrEquipmentId-kDDLOffset] = fPayloadCurr[6];
     645             :       fCurrL2rCount[fCurrEquipmentId-kDDLOffset] = fPayloadCurr[7];
     646             :     }
     647             : #endif
     648           0 :     break;
     649             : 
     650             :   default:
     651           0 :     AliError(Form("unknown SM header version: 0x%x", fCurrSmHeaderVersion));
     652           0 :   }
     653             : 
     654         216 :   AliDebug(5, Form("SM header: size: %i, version: %i, track enable: %i, tracklet enable: %i, stack mask: %2x, trailer: %i, trgheader: %i, trkheader: %i",
     655             :                    fCurrSmHeaderSize,
     656             :                    fCurrSmHeaderVersion,
     657             :                    fCurrTrackEnable,
     658             :                    fCurrTrackletEnable,
     659             :                    fCurrStackMask,
     660             :                    fCurrTrailerReadout,
     661             :                    fCurrTrgHeaderAvail,
     662             :                    fCurrTrkHeaderAvail ));
     663             : 
     664             :   // jump to the first word after the SM header
     665          72 :   fPayloadCurr += fCurrSmHeaderSize + 1;
     666             : 
     667          72 :   return fCurrSmHeaderSize + 1;
     668          72 : }
     669             : 
     670             : Int_t AliTRDrawStream::DecodeGTUtracks()
     671             : {
     672             :   // decode GTU track words
     673             :   // this depends on the hardware revision of the SMU
     674             : 
     675         144 :   Int_t sector = fCurrEquipmentId-kDDLOffset;
     676             : 
     677          72 :   if ((sector < 0) || (sector > 17)) {
     678           0 :     AliError(Form("Invalid sector %i for GTU tracks", sector));
     679           0 :     return -1;
     680             :   }
     681             : 
     682         216 :   AliDebug(1, DumpRaw(Form("GTU tracks in sector %2i (hw rev %i)", sector, fCurrHwRev),
     683             :                       fPayloadCurr + 4, 10, 0xffe0ffff));
     684             : 
     685          72 :   fCurrTrgFlags[sector] = 0;
     686             : 
     687          72 :   if (fCurrHwRev < 1772) {
     688             :     UInt_t    fastWord;         // fast trigger word
     689             :     ULong64_t trackWord = 0;    // extended track word
     690             :     Int_t stack = 0;
     691             :     Int_t idx = 0;
     692        9360 :     for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
     693        4608 :       if (fPayloadCurr[iWord] == 0x10000000) { // stack boundary marker
     694           0 :         stack++;
     695             :         idx = 0;
     696           0 :       }
     697             :       else {
     698        4680 :         if ((idx == 0) &&
     699          72 :             ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
     700             :           fastWord = fPayloadCurr[iWord];
     701           0 :           fCurrTrgFlags[sector] |= 1 << (stack+11); // assume tracking done if fast word sent
     702           0 :           AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
     703             :           continue;
     704             :         }
     705        9216 :         else if ((idx & 0x1) == 0x1) {
     706        6912 :           trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
     707        6912 :           AliDebug(1,Form("track debug word: 0x%016llx", trackWord));
     708        2304 :           if (fTracks) {
     709        2304 :             AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
     710        2304 :               AliESDTrdTrack();
     711             : 
     712        2304 :             trk->SetSector(sector);
     713        2304 :             trk->SetStack((trackWord >> 60) & 0x7);
     714        2304 :             trk->SetA(0);
     715        2304 :             trk->SetB(0);
     716        2304 :             trk->SetPID(0);
     717        2304 :             trk->SetLayerMask((trackWord >> 16) & 0x3f);
     718        2304 :             trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
     719        2304 :             trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
     720        2304 :             trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
     721        2304 :             trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
     722        2304 :             trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
     723        2304 :             trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
     724             : 
     725        2304 :             trk->SetFlags(0);
     726        2304 :             trk->SetReserved(0);
     727        2304 :             trk->SetLabel(-3);
     728             : 
     729        2304 :             Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
     730        2304 :             if (TMath::Abs(pt) > 0.1) {
     731           0 :               trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
     732           0 :             }
     733        2304 :           }
     734             :         }
     735             :         else {
     736             :           trackWord = fPayloadCurr[iWord];
     737             :         }
     738        4608 :         idx++;
     739             :       }
     740             :     }
     741          72 :   }
     742           0 :   else if (fCurrHwRev < 1804) {
     743             :     UInt_t    fastWord;         // fast trigger word
     744             :     ULong64_t trackWord = 0;    // extended track word
     745             :     Int_t stack = 0;
     746             :     Int_t idx = 0;
     747           0 :     for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
     748           0 :       if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
     749           0 :         stack++;
     750             :         idx = 0;
     751           0 :       }
     752             :       else {
     753           0 :         if ((idx == 0) &&
     754           0 :             ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
     755             :           fastWord = fPayloadCurr[iWord];
     756           0 :           fCurrTrgFlags[sector] |= 1 << (stack+11); // assume tracking done if fast word sent
     757           0 :           AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
     758             :           continue;
     759             :         }
     760           0 :         else if ((idx & 0x1) == 0x1) {
     761           0 :           trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
     762           0 :           AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
     763           0 :           if (fTracks) {
     764           0 :             AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
     765           0 :               AliESDTrdTrack();
     766             : 
     767           0 :             trk->SetSector(fCurrEquipmentId-kDDLOffset);
     768           0 :             trk->SetStack((trackWord >> 60) & 0x7);
     769           0 :             trk->SetA(0);
     770           0 :             trk->SetB(0);
     771           0 :             trk->SetPID(0);
     772           0 :             trk->SetLayerMask((trackWord >> 16) & 0x3f);
     773           0 :             trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
     774           0 :             trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
     775           0 :             trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
     776           0 :             trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
     777           0 :             trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
     778           0 :             trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
     779             : 
     780           0 :             trk->SetFlags(0);
     781           0 :             trk->SetReserved(0);
     782           0 :             trk->SetLabel(-3);
     783             : 
     784           0 :             Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
     785           0 :             if (TMath::Abs(pt) > 0.1) {
     786           0 :               trk->SetA((Int_t) (-0.15*51625./100./pt / 160e-4 * 2));
     787           0 :             }
     788           0 :           }
     789             :         }
     790             :         else {
     791             :           trackWord = fPayloadCurr[iWord];
     792             :         }
     793           0 :         idx++;
     794             :       }
     795             :     }
     796           0 :   }
     797           0 :   else if (fCurrHwRev < 1819) {
     798             :     UInt_t    fastWord;         // fast trigger word
     799             :     ULong64_t trackWord = 0;    // extended track word
     800             :     Int_t stack = 0;
     801             :     Int_t idx = 0;
     802           0 :     for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
     803           0 :       if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
     804           0 :         stack++;
     805             :         idx = 0;
     806           0 :       }
     807             :       else {
     808           0 :         if ((idx == 0) &&
     809           0 :             ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
     810             :           fastWord = fPayloadCurr[iWord];
     811           0 :           if (fastWord & (1 << 13))
     812           0 :             fCurrTrgFlags[sector] |= 1 << (stack+11);
     813           0 :           AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
     814             :           continue;
     815             :         }
     816           0 :         else if ((idx & 0x1) == 0x1) {
     817           0 :           trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
     818           0 :           AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
     819             : 
     820           0 :           if (fTracks) {
     821           0 :             AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
     822           0 :               AliESDTrdTrack();
     823             : 
     824           0 :             trk->SetSector(fCurrEquipmentId-kDDLOffset);
     825           0 :             trk->SetStack((trackWord >> 60) & 0x7);
     826           0 :             trk->SetA(0);
     827           0 :             trk->SetB(0);
     828             :             // trk->SetPt(((trackWord & 0xffff) ^ 0x8000) - 0x8000);
     829           0 :             trk->SetPID(0);
     830           0 :             trk->SetLayerMask((trackWord >> 16) & 0x3f);
     831           0 :             trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
     832           0 :             trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
     833           0 :             trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
     834           0 :             trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
     835           0 :             trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
     836           0 :             trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
     837             : 
     838           0 :             trk->SetFlags(0);
     839           0 :             trk->SetReserved(0);
     840           0 :             trk->SetLabel(-3);
     841             : 
     842           0 :             Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
     843           0 :             if (TMath::Abs(pt) > 0.1) {
     844           0 :               trk->SetA((Int_t) (0.15*51625./100./trk->Pt() / 160e-4 * 2));
     845           0 :             }
     846           0 :           }
     847             :         }
     848             :         else {
     849             :           trackWord = fPayloadCurr[iWord];
     850             :         }
     851           0 :         idx++;
     852             :       }
     853             :     }
     854           0 :   }
     855           0 :   else if (fCurrHwRev < 1860) {
     856             :     UInt_t    fastWord;         // fast trigger word
     857             :     ULong64_t trackWord = 0;    // extended track word
     858             :     Int_t stack = 0;
     859             :     Int_t idx = 0;
     860             :     Bool_t upperWord = kFALSE;
     861             :     Int_t word = 0;
     862           0 :     for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
     863           0 :       if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
     864           0 :         stack++;
     865             :         idx = 0;
     866             :         upperWord = kFALSE;
     867           0 :       }
     868             :       else {
     869             :         // assemble the 32-bit words out of 16-bit blocks
     870           0 :         if (upperWord) {
     871           0 :           word |= (fPayloadCurr[iWord] & 0xffff0000);
     872             :           upperWord = kFALSE;
     873             :         }
     874             :         else {
     875             :           // lower word is read first
     876           0 :           word = (fPayloadCurr[iWord] & 0xffff0000) >> 16;
     877             :           upperWord = kTRUE;
     878           0 :           continue;
     879             :         }
     880             : 
     881           0 :         if ((word & 0xffff0008) == 0x13370008) {
     882             :           fastWord = word;
     883           0 :           AliDebug(1, Form("stack %i: fast track word: 0x%08x", stack, fastWord));
     884           0 :           if (fastWord & (1 << 13))
     885           0 :             fCurrTrgFlags[sector] |= 1 << (stack+11);
     886             :           continue;
     887             :         }
     888           0 :         else if ((idx & 0x1) == 0x1) {
     889           0 :           trackWord |= ((ULong64_t) word) << 32;
     890           0 :           AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
     891           0 :           if (fTracks) {
     892           0 :             AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
     893           0 :               AliESDTrdTrack();
     894             : 
     895           0 :             trk->SetSector(fCurrEquipmentId-kDDLOffset);
     896           0 :             trk->SetStack((trackWord >> 60) & 0x7);
     897           0 :             trk->SetA(0);
     898           0 :             trk->SetB(0);
     899           0 :             trk->SetPID(0);
     900           0 :             trk->SetLayerMask((trackWord >> 16) & 0x3f);
     901           0 :             trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
     902           0 :             trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
     903           0 :             trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
     904           0 :             trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
     905           0 :             trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
     906           0 :             trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
     907             : 
     908           0 :             trk->SetFlags(0);
     909           0 :             trk->SetReserved(0);
     910           0 :             trk->SetLabel(-3);
     911             : 
     912           0 :             Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
     913           0 :             if (TMath::Abs(pt) > 0.1) {
     914           0 :               trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
     915           0 :             }
     916           0 :           }
     917             :         }
     918             :         else {
     919             :           trackWord = word;
     920             :         }
     921           0 :         idx++;
     922             :       }
     923             :     }
     924             : 
     925           0 :   }
     926             :   else {
     927             :     ULong64_t trackWord = 0; // this is the debug word
     928             :     Int_t stack = 0;
     929             :     Int_t idx = 0;
     930             :     Bool_t upperWord = kFALSE;
     931             :     Int_t word = 0;
     932           0 :     for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
     933           0 :       if (fPayloadCurr[iWord] == 0xffe0ffff) {
     934           0 :         stack++;
     935             :         idx = 0;
     936             :         upperWord = kFALSE;
     937           0 :       }
     938             :       else {
     939             :         // assemble the 32-bit words out of 16-bit blocks
     940           0 :         if (upperWord) {
     941           0 :           word |= (fPayloadCurr[iWord] & 0xffff0000);
     942             :           upperWord = kFALSE;
     943             :         }
     944             :         else {
     945             :           // lower word is read first
     946           0 :           word = (fPayloadCurr[iWord] & 0xffff0000) >> 16;
     947             :           upperWord = kTRUE;
     948           0 :           continue;
     949             :         }
     950             : 
     951           0 :         if ((word & 0xffff0008) == 0x13370008) {
     952           0 :           AliDebug(1, Form("stack %i: fast track word: 0x%08x", stack, word));
     953             :           continue;
     954             :         }
     955           0 :         else if ((word & 0xffff0010) == 0x13370010) {
     956           0 :           AliDebug(1, Form("stack %i: tracking done word: 0x%08x", stack, word));
     957           0 :           fCurrTrgFlags[sector] |= 1 << (stack+11);
     958           0 :           continue;
     959             :         }
     960           0 :         else if ((idx & 0x1) == 0x1) {
     961           0 :           trackWord |= ((ULong64_t) word) << 32;
     962           0 :           AliDebug(1, Form("track debug word: 0x%16llx", trackWord));
     963           0 :           if (fTracks) {
     964           0 :             AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
     965           0 :               AliESDTrdTrack();
     966           0 :             trk->SetSector(fCurrEquipmentId-kDDLOffset);
     967           0 :             trk->SetStack((trackWord >> 60) & 0x7);
     968           0 :             trk->SetA(0);
     969           0 :             trk->SetB(0);
     970           0 :             trk->SetPID(0);
     971           0 :             trk->SetLayerMask((trackWord >> 16) & 0x3f);
     972           0 :             trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
     973           0 :             trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
     974           0 :             trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
     975           0 :             trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
     976           0 :             trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
     977           0 :             trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
     978             : 
     979           0 :             trk->SetFlags(0);
     980           0 :             trk->SetReserved(0);
     981           0 :             trk->SetLabel(-3);
     982             : 
     983           0 :             Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
     984           0 :             if (TMath::Abs(pt) > 0.1) {
     985           0 :               trk->SetA(-(Int_t) (0.15*51625./100./pt / 160e-4 * 2));
     986           0 :             }
     987           0 :           }
     988             :         }
     989             :         else {
     990             :           trackWord = word;
     991             :         }
     992           0 :         idx++;
     993             :       }
     994             :     }
     995             :   }
     996          72 :   return 0;
     997          72 : }
     998             : 
     999             : Int_t AliTRDrawStream::ReadTrackingHeader(Int_t stack)
    1000             : {
    1001             :   // read the tracking information and store it for the given stack
    1002             : 
    1003             :   // index word
    1004             : 
    1005           0 :   fCurrTrkHeaderIndexWord[stack] = *fPayloadCurr;
    1006           0 :   fCurrTrkHeaderSize[stack]      = ((*fPayloadCurr) >> 16) & 0x3ff;
    1007             : 
    1008           0 :   AliDebug(1, Form("tracking header index word: 0x%08x, size: %i (hw rev: %i)",
    1009             :                    fCurrTrkHeaderIndexWord[stack], fCurrTrkHeaderSize[stack], fCurrHwRev));
    1010           0 :   Int_t trackingTime = *fPayloadCurr & 0x3ff;
    1011             : 
    1012           0 :   fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] |= ((fCurrTrkHeaderIndexWord[stack] >> 10) & 0x1) << (22 + stack);
    1013           0 :   fPayloadCurr++;
    1014             : 
    1015             :   // data words
    1016             :   ULong64_t trackWord = 0;
    1017             :   Int_t idx = 0;
    1018           0 :   Int_t trackIndex = fTracks ? fTracks->GetEntriesFast() : -1;
    1019             : 
    1020           0 :   for (UInt_t iWord = 0; iWord < fCurrTrkHeaderSize[stack]; iWord++) {
    1021             : 
    1022           0 :     if (!(idx & 0x1)) {
    1023             :       // first part of 64-bit word
    1024             :       trackWord = fPayloadCurr[iWord];
    1025           0 :     }
    1026             :     else {
    1027           0 :       trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
    1028             : 
    1029           0 :       if (trackWord & (1ul << 63)) {
    1030           0 :         if ((trackWord & (0x3ful << 56)) != 0) {
    1031             :           // track word
    1032           0 :           AliDebug(2, Form("track word: 0x%016llx", trackWord));
    1033             : 
    1034           0 :           if (fTracks) {
    1035           0 :             AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
    1036           0 :               AliESDTrdTrack();
    1037             : 
    1038           0 :             trk->SetSector(fCurrEquipmentId-kDDLOffset);
    1039           0 :             trk->SetLayerMask((trackWord >> 56) & 0x3f);
    1040           0 :             trk->SetA( (((trackWord >> 38) & 0x3ffff) ^ 0x20000) - 0x20000);
    1041           0 :             trk->SetB( (((trackWord >> 20) & 0x3ffff) ^ 0x20000) - 0x20000);
    1042           0 :             trk->SetC( (((trackWord >> 8)  &   0xfff) ^   0x800) -   0x800);
    1043           0 :             trk->SetPID((trackWord >>  0) & 0xff);
    1044           0 :             trk->SetStack(stack);
    1045           0 :             trk->SetLabel(-3);
    1046             : 
    1047             :             // now compare the track word with the one generated from the ESD information
    1048           0 :             if (trackWord != trk->GetTrackWord(0)) {
    1049           0 :               AliError(Form("track word 0x%016llx does not match the read one 0x%016llx",
    1050             :                             trk->GetTrackWord(0), trackWord));
    1051           0 :             }
    1052           0 :           }
    1053             :         }
    1054             :         else {
    1055             :           // done marker (so far only used to set trigger flag)
    1056           0 :           fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] |= 1 << (27 + stack);
    1057           0 :           fCurrTrkFlags[(fCurrEquipmentId-kDDLOffset)*fgkNstacks + stack] = trackWord;
    1058             : 
    1059           0 :           AliDebug(2, Form("tracking done marker: 0x%016llx, trigger flags: 0x%08x",
    1060             :                            trackWord, fCurrTrgFlags[fCurrEquipmentId-kDDLOffset]));
    1061           0 :           AliDebug(2, Form("seg / stack / first / last / done / index : %i %i %lli %lli %lli %i",
    1062             :                            fCurrEquipmentId - kDDLOffset, stack,
    1063             :                            (trackWord >> 20) & 0x3ff,
    1064             :                            (trackWord >> 10) & 0x3ff,
    1065             :                            (trackWord >>  0) & 0x3ff,
    1066             :                            trackingTime));
    1067             :         }
    1068             :       }
    1069             :       else {
    1070             :         // extended track word
    1071           0 :         AliDebug(2, Form("extended track word: 0x%016llx", trackWord));
    1072             : 
    1073           0 :         if (fTracks) {
    1074           0 :           AliESDTrdTrack *trk = (AliESDTrdTrack*) (*fTracks)[trackIndex];
    1075             : 
    1076           0 :           trk->SetFlags((trackWord >> 52) & 0x7ff);
    1077           0 :           trk->SetFlagsTiming((trackWord >> 51) & 0x1);
    1078           0 :           trk->SetReserved((trackWord >> 49) & 0x3);
    1079           0 :           trk->SetY((trackWord >> 36) & 0x1fff);
    1080           0 :           trk->SetTrackletIndex((trackWord >>  0) & 0x3f, 0);
    1081           0 :           trk->SetTrackletIndex((trackWord >>  6) & 0x3f, 1);
    1082           0 :           trk->SetTrackletIndex((trackWord >> 12) & 0x3f, 2);
    1083           0 :           trk->SetTrackletIndex((trackWord >> 18) & 0x3f, 3);
    1084           0 :           trk->SetTrackletIndex((trackWord >> 24) & 0x3f, 4);
    1085           0 :           trk->SetTrackletIndex((trackWord >> 30) & 0x3f, 5);
    1086             : 
    1087           0 :           if (trk->GetFlagsTiming() == 0) {
    1088           0 :             AliError(Form("*** track not in time: 0x%016llx", trk->GetExtendedTrackWord(0)));
    1089           0 :           }
    1090             : 
    1091           0 :           if (trackWord != trk->GetExtendedTrackWord(0)) {
    1092           0 :             AliError(Form("extended track word 0x%016llx does not match the read one 0x%016llx",
    1093             :                           trk->GetExtendedTrackWord(0), trackWord));
    1094           0 :             }
    1095             : 
    1096           0 :           trackIndex++;
    1097           0 :         }
    1098             :       }
    1099             :     }
    1100           0 :     idx++;
    1101             :   }
    1102             : 
    1103           0 :   fPayloadCurr += fCurrTrkHeaderSize[stack];
    1104             : 
    1105           0 :   return fCurrTrkHeaderSize[stack];
    1106           0 : }
    1107             : 
    1108             : Int_t AliTRDrawStream::ReadTriggerHeaders()
    1109             : {
    1110             :   // read all trigger headers present
    1111             : 
    1112           0 :   AliDebug(1, Form("trigger mask: 0x%03x, fired: 0x%03x\n",
    1113             :                    fCurrTriggerEnable, fCurrTriggerFired));
    1114             :   // loop over potential trigger blocks
    1115           0 :   for (Int_t iTrigger = 0; iTrigger < fgkNtriggers; iTrigger++) {
    1116             :     // check for trigger enable
    1117           0 :     if (fCurrTriggerEnable & (1 << iTrigger)) {
    1118             :       // check for readout mode and trigger fired
    1119           0 :       if ((fCurrTrgHeaderReadout == 0) || (fCurrTriggerFired & (1 << iTrigger))) {
    1120             :         // index word
    1121           0 :         AliDebug(1, Form("trigger index word %i: 0x%08x\n", iTrigger, *fPayloadCurr));
    1122           0 :         fCurrTrgHeaderIndexWord[iTrigger] = *fPayloadCurr;
    1123           0 :         fCurrTrgHeaderSize[iTrigger]      = ((*fPayloadCurr) >> 16) & 0x3ff;
    1124           0 :         if (iTrigger == 7) {
    1125             :           // timeout trigger, use to extract tracking time
    1126           0 :           fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] |= (*fPayloadCurr & 0x3ff) << 12;
    1127           0 :         }
    1128             : 
    1129           0 :         fPayloadCurr++;
    1130             :         // data words
    1131           0 :         fPayloadCurr += fCurrTrgHeaderSize[iTrigger];
    1132           0 :       }
    1133             :     }
    1134             :   }
    1135             : 
    1136           0 :   return 0;
    1137             : }
    1138             : 
    1139             : Int_t AliTRDrawStream::ReadStackHeader(Int_t stack)
    1140             : {
    1141             :   // read the stack header
    1142             :   // and store the information in the corresponding variables
    1143             : 
    1144         720 :   fCurrStackIndexWord[stack]     = *fPayloadCurr;
    1145         360 :   fCurrStackHeaderSize[stack]    = (((*fPayloadCurr) >> 16) & 0xffff) + 1;
    1146         360 :   fCurrStackHeaderVersion[stack] = ((*fPayloadCurr) >> 12) & 0xf;
    1147         360 :   fCurrLinkMask[stack]           = (*fPayloadCurr) & 0xfff;
    1148             : 
    1149             :   // dumping stack header
    1150        1080 :   AliDebug(1, DumpRaw(Form("stack %i header", stack), fPayloadCurr, fCurrStackHeaderSize[stack]));
    1151             : 
    1152         360 :   if (fPayloadCurr - fPayloadStart >= fPayloadSize - (Int_t) fCurrStackHeaderSize[stack]) {
    1153           0 :     EquipmentError(kStackHeaderInvalid, "Stack index header %i incomplete", stack);
    1154             :     // dumping stack header
    1155           0 :     AliError(DumpRaw(Form("stack %i header", stack), fPayloadCurr, fCurrStackHeaderSize[stack]));
    1156             : 
    1157           0 :     return -1;
    1158             :   }
    1159             : 
    1160         360 :   switch (fCurrStackHeaderVersion[stack]) {
    1161             :   case 0xa:
    1162             :   case 0xb:
    1163         360 :     if (fCurrStackHeaderSize[stack] < 8) {
    1164           0 :       LinkError(kStackHeaderInvalid, "Stack header smaller than expected!");
    1165           0 :       return -1;
    1166             :     }
    1167             : 
    1168         360 :     fCurrCleanCheckout[stack] = fPayloadCurr[1] & 0x1;
    1169         360 :     fCurrBoardId[stack]       = (fPayloadCurr[1] >> 8) & 0xff;
    1170         360 :     fCurrHwRevTMU[stack]      = (fPayloadCurr[1] >> 16) & 0xffff;
    1171             : 
    1172        5040 :     for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
    1173             :       // A side
    1174        2160 :       fCurrLinkMonitorFlags  [((fCurrEquipmentId - kDDLOffset) * fgkNstacks + stack) *fgkNlinks + iLayer*2] = fPayloadCurr[iLayer+2] & 0xf;
    1175        2160 :       fCurrLinkDataTypeFlags [stack * fgkNlinks + iLayer*2]      = (fPayloadCurr[iLayer+2] >> 4) & 0x3;
    1176        2160 :       fCurrLinkDebugFlags    [stack * fgkNlinks + iLayer*2]      = (fPayloadCurr[iLayer+2] >> 12) & 0xf;
    1177             :       // B side
    1178        2160 :       fCurrLinkMonitorFlags  [((fCurrEquipmentId - kDDLOffset) * fgkNstacks + stack) *fgkNlinks + iLayer*2 + 1] = (fPayloadCurr[iLayer+2] >> 16) & 0xf;
    1179        2160 :       fCurrLinkDataTypeFlags [stack * fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 20) & 0x3;
    1180        2160 :       fCurrLinkDebugFlags    [stack * fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 28) & 0xf;
    1181             :     }
    1182         360 :     break;
    1183             : 
    1184             :   default:
    1185           0 :     EquipmentError(kStackHeaderInvalid, "Invalid Stack Header version %x", fCurrStackHeaderVersion[stack]);
    1186           0 :   }
    1187             : 
    1188         360 :   fPayloadCurr += fCurrStackHeaderSize[stack];
    1189             : 
    1190         360 :   return fCurrStackHeaderSize[stack];
    1191         360 : }
    1192             : 
    1193             : Int_t AliTRDrawStream::ReadGTUTrailer()
    1194             : {
    1195             :   // read the SM trailer containing CRCs from various stages
    1196             : 
    1197           0 :   UInt_t* trailer = fPayloadStart + fPayloadSize -1;
    1198             : 
    1199             :   // look for the trailer index word from the end
    1200           0 :   for (Int_t iWord = 0; iWord < fPayloadSize-2; iWord++) {
    1201           0 :     if ((fPayloadStart[fPayloadSize-3-iWord] == fgkStackEndmarker[0]) &&
    1202           0 :         (fPayloadStart[fPayloadSize-2-iWord] == fgkStackEndmarker[1]) &&
    1203           0 :         ((fPayloadStart[fPayloadSize-1-iWord] & 0xfff) == 0xf51)) {
    1204           0 :       trailer = fPayloadStart + fPayloadSize - 1 - iWord;
    1205           0 :       break;
    1206             :     }
    1207             :   }
    1208             : 
    1209           0 :   if (((*trailer) & 0xfff) == 0xf51) {
    1210             :     UInt_t trailerIndexWord = (*trailer);
    1211           0 :     Int_t trailerSize = (trailerIndexWord >> 16) & 0xffff;
    1212             :     // Int_t trailerVersion = (trailerIndexWord >> 12) & 0xf;
    1213           0 :     AliDebug(2, DumpRaw("GTU trailer", trailer, trailerSize+1));
    1214             :     // parse the trailer
    1215           0 :     if (trailerSize >= 4) {
    1216             :       // match flags from GTU
    1217           0 :       fCurrMatchFlagsSRAM[fCurrEquipmentId-kDDLOffset]     = (trailer[1] >>  0) &    0x1f;
    1218           0 :       fCurrMatchFlagsPostBP[fCurrEquipmentId-kDDLOffset]   = (trailer[1] >>  5) &    0x1f;
    1219             :       // individual checksums
    1220           0 :       fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][0]   = (trailer[1] >> 16) &  0xffff;
    1221           0 :       fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][1]   = (trailer[2] >>  0) &  0xffff;
    1222           0 :       fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][2]   = (trailer[2] >> 16) &  0xffff;
    1223           0 :       fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][3]   = (trailer[3] >>  0) &  0xffff;
    1224           0 :       fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][4]   = (trailer[3] >> 16) &  0xffff;
    1225           0 :       fCurrChecksumSIU        = trailer[trailerSize];
    1226             : 
    1227           0 :       if ((fCurrMatchFlagsSRAM[fCurrEquipmentId-kDDLOffset] & fCurrStackMask) != fCurrStackMask)
    1228           0 :         EquipmentError(kCRCmismatch, "CRC mismatch SRAM: 0x%02x", fCurrMatchFlagsSRAM[fCurrEquipmentId-kDDLOffset]);
    1229           0 :       if ((fCurrMatchFlagsPostBP[fCurrEquipmentId-kDDLOffset] & fCurrStackMask) != fCurrStackMask)
    1230           0 :         EquipmentError(kCRCmismatch, "CRC mismatch BP: 0x%02x", fCurrMatchFlagsPostBP[fCurrEquipmentId-kDDLOffset]);
    1231             : 
    1232             :     }
    1233             :     else {
    1234           0 :       LinkError(kUnknown, "Invalid GTU trailer");
    1235             :     }
    1236           0 :   }
    1237             :   else
    1238           0 :     EquipmentError(kUnknown, "trailer index marker mismatch");
    1239             : 
    1240           0 :   return 0;
    1241           0 : }
    1242             : 
    1243             : Int_t AliTRDrawStream::ReadLinkData()
    1244             : {
    1245             :   // read the data in one link (one HC) until the data endmarker is reached
    1246             :   // returns the number of words read!
    1247             : 
    1248             :   Int_t count = 0;
    1249        8640 :   UInt_t* startPosLink = fPayloadCurr;
    1250             : 
    1251       12960 :   AliDebug(1, DumpRaw(Form("link data from seg %2i slot %i link %2i", fCurrEquipmentId-kDDLOffset, fCurrSlot, fCurrLink),
    1252             :                       fPayloadCurr, TMath::Min((Int_t) (fPayloadSize - (fPayloadCurr-fPayloadStart)), 100), 0x00000000));
    1253             : 
    1254        4320 :   if (fMarkers)
    1255           0 :     new ((*fMarkers)[fMarkers->GetEntriesFast()])
    1256           0 :       AliTRDrawStreamError(-kHCactive, fCurrEquipmentId-kDDLOffset, fCurrSlot, fCurrLink);
    1257             : 
    1258        4320 :   if (fErrorFlags & kDiscardHC)
    1259           0 :     return count;
    1260             : 
    1261        4320 :   if (fCurrTrackletEnable) {
    1262        4320 :     count += ReadTracklets();
    1263        4320 :     if (fErrorFlags & kDiscardHC)
    1264           0 :       return count;
    1265             :   }
    1266             : 
    1267       12960 :   AliDebug(1, DumpRaw("HC header", fPayloadCurr, 4, 0x00000000));
    1268        4320 :   count += ReadHcHeader();
    1269        4320 :   if (fErrorFlags & kDiscardHC)
    1270           0 :     return count;
    1271             : 
    1272        4320 :   Int_t det = fCurrSm * 30 + fCurrStack * 6 + fCurrLayer;
    1273             : 
    1274        4320 :   if (det > -1 && det < 540) {
    1275             : 
    1276             :     // ----- check which kind of data -----
    1277        4320 :     if (fCurrMajor & 0x40) {
    1278           0 :       if ((fCurrMajor & 0x7) == 0x7) {
    1279           0 :         AliDebug(1, "This is a config event");
    1280           0 :         UInt_t *startPos = fPayloadCurr;
    1281           0 :         while (fPayloadCurr - fPayloadStart < fPayloadSize &&
    1282           0 :                *fPayloadCurr != fgkDataEndmarker)
    1283           0 :           fPayloadCurr++;
    1284           0 :         count += fPayloadCurr - startPos;
    1285             : 
    1286             :         // feeding TRAP config
    1287           0 :         AliTRDtrapConfig *trapcfg = AliTRDcalibDB::Instance()->GetTrapConfig();
    1288           0 :         AliTRDmcmSim::ReadPackedConfig(trapcfg, fCurrHC, startPos, fPayloadCurr - startPos);
    1289           0 :       }
    1290             :       else {
    1291             :         Int_t tpmode = fCurrMajor & 0x7;
    1292           0 :         AliDebug(1, Form("Checking testpattern (mode %i) data", tpmode));
    1293           0 :         count += ReadTPData(tpmode);
    1294             :       }
    1295             :     }
    1296             :     else {
    1297             :       // reading real data
    1298        4320 :       if (fDigitsManager) {
    1299        4320 :         if ((fAdcArray = fDigitsManager->GetDigits(det))) {
    1300             :           //fAdcArray->Expand();
    1301        4320 :           if (fAdcArray->GetNtime() != fCurrNtimebins)
    1302         541 :             fAdcArray->Allocate(16, 144, fCurrNtimebins);
    1303             :         }
    1304             :         else {
    1305           0 :           LinkError(kNoDigits);
    1306             :         }
    1307             : 
    1308        4320 :         if (!fDigitsParam) {
    1309        2160 :           fDigitsParam = fDigitsManager->GetDigitsParam();
    1310        2160 :         }
    1311        4320 :         if (fDigitsParam) {
    1312        4320 :           fDigitsParam->SetPretriggerPhase(det, fCurrPtrgPhase);
    1313        4320 :           fDigitsParam->SetNTimeBins(det, fCurrNtimebins);
    1314        4320 :           fDigitsParam->SetADCbaseline(det, 10);
    1315        4320 :         }
    1316             : 
    1317        4320 :         if (fDigitsManager->UsesDictionaries()) {
    1318           0 :           fDigitsManager->GetDictionary(det, 0)->Reset();
    1319           0 :           fDigitsManager->GetDictionary(det, 1)->Reset();
    1320           0 :           fDigitsManager->GetDictionary(det, 2)->Reset();
    1321           0 :         }
    1322             : 
    1323        4320 :         if ((fSignalIndex = fDigitsManager->GetIndexes(det))) {
    1324        4320 :           fSignalIndex->SetSM(fCurrSm);
    1325        4320 :           fSignalIndex->SetStack(fCurrStack);
    1326        4320 :           fSignalIndex->SetLayer(fCurrLayer);
    1327        4320 :           fSignalIndex->SetDetNumber(det);
    1328        4320 :           if (!fSignalIndex->IsAllocated())
    1329         541 :             fSignalIndex->Allocate(16, 144, fCurrNtimebins);
    1330             :         }
    1331             : 
    1332        8640 :         if (fCurrMajor & 0x20) {
    1333       17280 :           AliDebug(1, "This is a zs event");
    1334        4320 :           count += ReadZSData();
    1335        4320 :         }
    1336             :         else {
    1337           0 :           AliDebug(1, "This is a nozs event");
    1338           0 :           count += ReadNonZSData();
    1339             :         }
    1340             :       }
    1341             :       else {
    1342             :         // just read until data endmarkers
    1343           0 :         while (fPayloadCurr - fPayloadStart < fPayloadSize &&
    1344           0 :                *fPayloadCurr != fgkDataEndmarker)
    1345           0 :           fPayloadCurr++;
    1346             :       }
    1347             :     }
    1348             :   }
    1349             :   else {
    1350           0 :     LinkError(kInvalidDetector, "%i", det);
    1351           0 :     while (fPayloadCurr - fPayloadStart < fPayloadSize &&
    1352           0 :            *fPayloadCurr != fgkDataEndmarker)
    1353           0 :       fPayloadCurr++;
    1354             :   }
    1355             : 
    1356        8640 :   if (fCurrSm > -1 && fCurrSm < 18) {
    1357        4320 :     fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytes     += (fPayloadCurr - startPosLink) * sizeof(UInt_t);
    1358        4320 :     fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytesRead += count * sizeof(UInt_t);
    1359        4320 :     fStats.fStatsSector[fCurrSm].fBytesRead                      += count * sizeof(UInt_t);
    1360        4320 :     fStats.fBytesRead                                            += count * sizeof(UInt_t);
    1361        4320 :   }
    1362             : 
    1363        4320 :   if ((fErrorFlags & kDiscardHC) && fAdcArray)
    1364           0 :     fAdcArray->SetDataInvalid(); // invalidate the data
    1365             : 
    1366             :   return count;
    1367        4320 : }
    1368             : 
    1369             : Int_t AliTRDrawStream::ReadTracklets()
    1370             : {
    1371             :   // read the tracklets from one HC
    1372             : 
    1373             :   Int_t nTracklets = 0;
    1374             : 
    1375        8640 :   UInt_t *start = fPayloadCurr;
    1376       14037 :   while (*(fPayloadCurr) != fgkTrackletEndmarker &&
    1377         359 :          *(fPayloadCurr) != fgkStackEndmarker[0] &&
    1378         359 :          *(fPayloadCurr) != fgkStackEndmarker[1] &&
    1379         359 :          fPayloadCurr - fPayloadStart < (fPayloadSize - 1)) {
    1380         359 :     ++nTracklets;
    1381         359 :     if (fTracklets)
    1382         359 :       new ((*fTracklets)[fTracklets->GetEntriesFast()]) AliTRDtrackletWord(*(fPayloadCurr), fCurrHC);
    1383             : 
    1384         359 :     fPayloadCurr++;
    1385             :   }
    1386             : 
    1387        4320 :   if (nTracklets > 0) {
    1388         495 :     AliDebug(1, Form("Found %i tracklets in %i %i %i (ev. %i)", nTracklets,
    1389             :                      (fCurrEquipmentId-kDDLOffset), fCurrSlot, fCurrLink, fRawReader->GetEventIndex()));
    1390         330 :     if (fCurrSm > -1 && fCurrSm < 18) {
    1391         165 :       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNTracklets += nTracklets;
    1392         165 :       fStats.fStatsSector[fCurrSm].fNTracklets                      += nTracklets;
    1393         165 :     }
    1394             :   }
    1395             : 
    1396             :   // loop over remaining tracklet endmarkers
    1397       34560 :   while ((*(fPayloadCurr) == fgkTrackletEndmarker &&
    1398        8640 :           fPayloadCurr - fPayloadStart < fPayloadSize))
    1399       21600 :     fPayloadCurr++;
    1400             : 
    1401        4320 :   return fPayloadCurr - start;
    1402           0 : }
    1403             : 
    1404             : Int_t AliTRDrawStream::ReadHcHeader()
    1405             : {
    1406             :   // read and parse the HC header of one HC
    1407             :   // and store the information in the corresponding variables
    1408             : 
    1409       17280 :   AliDebug(1, Form("HC header: 0x%08x", *fPayloadCurr));
    1410        4320 :   UInt_t *start = fPayloadCurr;
    1411             :   // check not to be at the data endmarker
    1412        8640 :   if (*fPayloadCurr == fgkDataEndmarker ||
    1413        4320 :       *(fPayloadCurr) == fgkStackEndmarker[0] ||
    1414        4320 :       *(fPayloadCurr) == fgkStackEndmarker[1]) {
    1415           0 :     LinkError(kHCmismatch, "found endmarker where HC header should be");
    1416           0 :     return 0;
    1417             :   }
    1418             : 
    1419        4320 :   fCurrSpecial    = (*fPayloadCurr >> 31) & 0x1;
    1420        4320 :   fCurrMajor      = (*fPayloadCurr >> 24) & 0x7f;
    1421        4320 :   fCurrMinor      = (*fPayloadCurr >> 17) & 0x7f;
    1422        4320 :   fCurrAddHcWords = (*fPayloadCurr >> 14) & 0x7;
    1423        4320 :   fCurrSm         = (*fPayloadCurr >> 9) & 0x1f;
    1424        4320 :   fCurrLayer      = (*fPayloadCurr >> 6) & 0x7;
    1425        4320 :   fCurrStack      = (*fPayloadCurr >> 3) & 0x7;
    1426        4320 :   fCurrSide       = (*fPayloadCurr >> 2) & 0x1;
    1427        4320 :   fCurrCheck      = (*fPayloadCurr) & 0x3;
    1428             : 
    1429        8640 :   if ((fCurrSm != (((Int_t) fCurrEquipmentId) - kDDLOffset)) ||
    1430        4320 :       (fCurrStack != fCurrSlot) ||
    1431        4320 :       (fCurrLayer != fCurrLink / 2) ||
    1432        4320 :       (fCurrSide != fCurrLink % 2)) {
    1433           0 :     LinkError(kHCmismatch,
    1434             :               "HC: %i, %i, %i, %i\n 0x%08x 0x%08x 0x%08x 0x%08x",
    1435           0 :               fCurrSm, fCurrStack, fCurrLayer, fCurrSide,
    1436           0 :               fPayloadCurr[0], fPayloadCurr[1], fPayloadCurr[2], fPayloadCurr[3]);
    1437           0 :   }
    1438        4320 :   if (fCurrCheck != 0x1) {
    1439           0 :     LinkError(kHCcheckFailed);
    1440           0 :   }
    1441             : 
    1442        4320 :   if (fCurrAddHcWords > 0) {
    1443        4320 :     fCurrNtimebins = (fPayloadCurr[1] >> 26) & 0x3f;
    1444             : #ifdef TRD_RAW_DEBUG
    1445             :     fCurrBC[fCurrHC] = (fPayloadCurr[1] >> 10) & 0xffff;
    1446             : #endif
    1447        4320 :     fCurrPtrgCnt = (fPayloadCurr[1] >> 6) & 0xf;
    1448        4320 :     fCurrPtrgPhase = (fPayloadCurr[1] >> 2) & 0xf;
    1449        4320 :   }
    1450             : 
    1451        4320 :   fPayloadCurr += 1 + fCurrAddHcWords;
    1452             : 
    1453        4320 :   return (fPayloadCurr - start);
    1454        4320 : }
    1455             : 
    1456             : Int_t AliTRDrawStream::ReadTPData(Int_t mode)
    1457             : {
    1458             :   // testing of testpattern 1 to 3 (hardcoded), 0 missing
    1459             :   // evcnt checking missing
    1460             :   Int_t cpu = 0;
    1461           0 :   Int_t cpufromchannel[] = {0, 0, 0, 0, 0,  1, 1, 1, 1, 1,  2, 2, 2, 2, 2,  3, 3, 3, 3, 3, 3};
    1462             :   Int_t evno  = -1;
    1463             :   Int_t evcnt = 0;
    1464             :   Int_t count = 0;
    1465             :   Int_t mcmcount = -1;
    1466             :   Int_t wordcount = 0;
    1467             :   Int_t channelcount = 0;
    1468             :   UInt_t expword = 0;
    1469             :   UInt_t expadcval = 0;
    1470             :   UInt_t diff = 0;
    1471             :   Int_t lastmcmpos = -1;
    1472             :   Int_t lastrobpos = -1;
    1473             : 
    1474           0 :   UInt_t* start = fPayloadCurr;
    1475             : 
    1476           0 :   while (*(fPayloadCurr) != fgkDataEndmarker &&
    1477           0 :          fPayloadCurr - fPayloadStart < fPayloadSize - 1) {
    1478             : 
    1479             :     // ----- Checking MCM Header -----
    1480           0 :     AliDebug(2, DumpMcmHeader("MCM header: ", *fPayloadCurr));
    1481           0 :     UInt_t *startPosMCM = fPayloadCurr;
    1482           0 :     mcmcount++;
    1483             : 
    1484             :     // ----- checking for proper readout order - ROB -----
    1485           0 :     fCurrRobPos = ROB(*fPayloadCurr);
    1486           0 :     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
    1487           0 :       if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
    1488           0 :         lastmcmpos = -1;
    1489           0 :       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
    1490           0 :     }
    1491             :     else {
    1492           0 :       ROBError(kPosUnexp, Form("#%i after #%i in readout order", GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos));
    1493             :     }
    1494             : 
    1495             :     // ----- checking for proper readout order - MCM -----
    1496           0 :     fCurrMcmPos = MCM(*fPayloadCurr);
    1497           0 :     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
    1498           0 :       lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
    1499           0 :     }
    1500             :     else {
    1501           0 :       MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
    1502             :     }
    1503             : 
    1504           0 :     if (EvNo(*fPayloadCurr) != (evno & 0xfffff)) {
    1505           0 :       if (evno == -1) {
    1506           0 :         evno = EvNo(*fPayloadCurr);
    1507           0 :       }
    1508             :       else {
    1509           0 :         MCMError(kEvCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
    1510             : #ifdef TRD_RAW_DEBUG
    1511             :         if (fCurrL0offset[fCurrHC/2] != 0)
    1512             :           LinkError(kEvCntMismatch, "offset for %i %i %i changed from %i to %i = %i - %i",
    1513             :                     fCurrEquipmentId, fCurrSlot, fCurrLink/2, fCurrL0offset[fCurrHC/2],
    1514             :                     EvNo(*fPayloadCurr) - fCurrL0Count[fCurrEquipmentId-kDDLOffset],
    1515             :                     EvNo(*fPayloadCurr), fCurrL0Count[fCurrEquipmentId-kDDLOffset]);
    1516             :         fCurrL0offset[fCurrHC/2] = EvNo(*fPayloadCurr) - fCurrL0Count[fCurrEquipmentId-kDDLOffset];
    1517             :         evno = fCurrL0Count[fCurrEquipmentId-kDDLOffset] + fCurrL0offset[fCurrHC/2];
    1518             : #endif
    1519             :       }
    1520             :     }
    1521             : 
    1522           0 :     fPayloadCurr++;
    1523             : 
    1524           0 :     evcnt = 0x3f & *fPayloadCurr >> 26;
    1525             :     cpu = -1;
    1526             :     channelcount = 0;
    1527           0 :     while (channelcount < 21) {
    1528             :       count = 0;
    1529           0 :       if (cpu != cpufromchannel[channelcount]) {
    1530             :         cpu = cpufromchannel[channelcount];
    1531           0 :         expadcval = (1 << 9) | (fCurrRobPos << 6) | (fCurrMcmPos << 2) | cpu;
    1532             :         wordcount = 0;
    1533           0 :       }
    1534             : 
    1535           0 :       while (count < 10) {
    1536           0 :         if (*fPayloadCurr == fgkDataEndmarker) {
    1537           0 :           MCMError(kMissTpData);
    1538           0 :           return (fPayloadCurr - start);
    1539             :         }
    1540             : 
    1541           0 :         if (channelcount % 2 == 0)
    1542           0 :           expword = 0x3;
    1543             :         else
    1544             :           expword = 0x2;
    1545             : 
    1546           0 :         if (mode == 1) {
    1547             :           // ----- TP 1 -----
    1548           0 :           expword |= expadcval << 2;
    1549           0 :           expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
    1550           0 :           expword |= expadcval << 12;
    1551           0 :           expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
    1552           0 :           expword |= expadcval << 22;
    1553           0 :           expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
    1554           0 :         }
    1555           0 :         else if (mode == 2) {
    1556             :           // ----- TP 2 ------
    1557           0 :           expword = ((0x3f & evcnt) << 26) | ((fCurrSm + 1) << 21) | ((fCurrLayer + 1) << 18) |
    1558           0 :             ((fCurrStack + 1) << 15) |
    1559           0 :             (fCurrRobPos << 12) | (fCurrMcmPos << 8) | (cpu << 6) | (wordcount + 1);
    1560           0 :         }
    1561           0 :         else if (mode == 3) {
    1562             :           // ----- TP 3 -----
    1563           0 :           expword = ((0xfff & evcnt) << 20) | (fCurrSm << 15) | (fCurrLink/2 << 12) | (fCurrStack << 9) |
    1564           0 :             (fCurrRobPos << 6) | (fCurrMcmPos << 2) | (cpu << 0);
    1565           0 :         }
    1566             :         else {
    1567             :           expword = 0;
    1568           0 :           LinkError(kTPmodeInvalid, "Just reading");
    1569             :         }
    1570             : 
    1571           0 :         diff = *fPayloadCurr ^ expword;
    1572           0 :         AliDebug(11, Form("Comparing ch %2i, word %2i (cpu %i): 0x%08x <-> 0x%08x",
    1573             :                           channelcount, wordcount, cpu, *fPayloadCurr, expword));
    1574             : 
    1575           0 :         if (diff != 0) {
    1576           0 :           MCMError(kTPmismatch,
    1577             :                    "Seen 0x%08x, expected 0x%08x, diff: 0x%08x, 0x%04x, 0x%02x - word %2i (cpu %i, ch %i)",
    1578           0 :                    *fPayloadCurr, expword, diff,
    1579           0 :                    0xffff & (diff | diff >> 16),
    1580           0 :                    0xff & (diff | diff >> 8 | diff >> 16 | diff >> 24),
    1581             :                    wordcount, cpu, channelcount);;
    1582           0 :         }
    1583           0 :         fPayloadCurr++;
    1584           0 :         count++;
    1585           0 :         wordcount++;
    1586           0 :         if (*fPayloadCurr == fgkDataEndmarker)
    1587           0 :           return (fPayloadCurr - start);
    1588             :       }
    1589           0 :       channelcount++;
    1590             :     }
    1591             :     // continue with next MCM
    1592             : 
    1593           0 :     if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
    1594           0 :       AliInfo(DumpRaw(Form("Event %i: Det %3i ROB %i MCM %2i", fRawReader->GetEventIndex(), fCurrHC/2, fCurrRobPos, fCurrMcmPos),
    1595             :                       startPosMCM, fPayloadCurr - startPosMCM));
    1596           0 :     }
    1597             : 
    1598           0 :   }
    1599           0 :   return fPayloadCurr - start;
    1600           0 : }
    1601             : 
    1602             : 
    1603             : Int_t AliTRDrawStream::ReadZSData()
    1604             : {
    1605             :   // read the zs data from one link from the current reading position
    1606             : 
    1607        8640 :   UInt_t *start = fPayloadCurr;
    1608             : 
    1609             :   Int_t mcmcount = 0;
    1610        4320 :   Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
    1611             :   Int_t channelcount = 0;
    1612             :   Int_t channelcountExp = 0;
    1613             :   Int_t channelcountMax = 0;
    1614             :   Int_t timebins;
    1615             :   Int_t currentTimebin = 0;
    1616             :   Int_t adcwc = 0;
    1617             :   Int_t evno = -1;
    1618             :   Int_t lastmcmpos = -1;
    1619             :   Int_t lastrobpos = -1;
    1620             : 
    1621        4320 :   if (fCurrNtimebins != fNtimebins) {
    1622           2 :     if (fNtimebins > 0)
    1623           0 :       LinkError(kNtimebinsChanged,
    1624             :                 "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
    1625           2 :     fNtimebins = fCurrNtimebins;
    1626           2 :   }
    1627             : 
    1628        4320 :   timebins = fNtimebins;
    1629             : 
    1630        9806 :   while (*(fPayloadCurr) != fgkDataEndmarker &&
    1631         583 :          *(fPayloadCurr) != fgkStackEndmarker[0] &&
    1632         583 :          *(fPayloadCurr) != fgkStackEndmarker[1] &&
    1633         583 :          fPayloadCurr - fPayloadStart < fPayloadSize) {
    1634             : 
    1635             :     // ----- Checking MCM Header -----
    1636        1749 :     AliDebug(2, DumpMcmHeader("MCM header: ", *fPayloadCurr));
    1637         583 :     UInt_t *startPosMCM = fPayloadCurr;
    1638             : 
    1639             :     // ----- checking for proper readout order - ROB -----
    1640         583 :     fCurrRobPos = ROB(*fPayloadCurr);
    1641        1166 :     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
    1642        1166 :       if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
    1643         305 :         lastmcmpos = -1;
    1644         583 :       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
    1645         583 :     }
    1646             :     else {
    1647           0 :       ROBError(kPosUnexp, Form("#%i after #%i and #%i in readout order",
    1648           0 :                                GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos, GetROBReadoutPos(fCurrRobPos)));
    1649             :     }
    1650             : 
    1651             :     // ----- checking for proper readout order - MCM -----
    1652         583 :     fCurrMcmPos = MCM(*fPayloadCurr);
    1653        1166 :     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
    1654         583 :       lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
    1655         583 :     }
    1656             :     else {
    1657           0 :       MCMError(kPosUnexp, Form("#%i after #%i and #%i in readout order",
    1658           0 :                                GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos, GetMCMReadoutPos(fCurrMcmPos)));
    1659             :     }
    1660             : 
    1661             : #ifdef TRD_RAW_DEBUG
    1662             :     if (fCurrL0Count[fCurrEquipmentId-kDDLOffset] > 0) {
    1663             :       evno = fCurrL0Count[fCurrEquipmentId-kDDLOffset] + fCurrL0offset[fCurrHC/2];
    1664             :     }
    1665             :     fCurrEvCount[fCurrEquipmentId-kDDLOffset] = EvNo(*fPayloadCurr);
    1666             : #endif
    1667             : 
    1668         583 :     if (EvNo(*fPayloadCurr) != (evno & 0xfffff)) {
    1669         238 :       if (evno == -1) {
    1670         238 :         evno = EvNo(*fPayloadCurr);
    1671         238 :       }
    1672             :       else {
    1673           0 :         MCMError(kEvCntMismatch, "exp <-> SM: %i <-> %i", evno & 0xfffff, EvNo(*fPayloadCurr));
    1674             : #ifdef TRD_RAW_DEBUG
    1675             :         Int_t prevOffset = fCurrL0offset[fCurrHC/2];
    1676             :         fCurrL0offset[fCurrHC/2] = (- fCurrL0Count[fCurrEquipmentId-kDDLOffset] + EvNo(*fPayloadCurr)) % (1 << 20);
    1677             :         if (fCurrL0offset[fCurrHC/2] < 0)
    1678             :           fCurrL0offset[fCurrHC/2] += 0xfffff;
    1679             :         evno = (fCurrL0Count[fCurrEquipmentId-kDDLOffset] + fCurrL0offset[fCurrHC/2]) & 0xfffff;
    1680             :         if (prevOffset != 0)
    1681             :           LinkError(kEvCntMismatch, "offset for %i %i %i changed from %i to %i = %i - %i",
    1682             :                     fCurrEquipmentId, fCurrSlot, fCurrLink/2,
    1683             :                     prevOffset,
    1684             :                     fCurrL0offset[fCurrHC/2],
    1685             :                     fCurrL0Count[fCurrEquipmentId-kDDLOffset],
    1686             :                     EvNo(*fPayloadCurr));
    1687             : #endif
    1688             :       }
    1689             :     }
    1690         583 :     Int_t adccoloff = AdcColOffset(*fPayloadCurr);
    1691         583 :     Int_t padcoloff = PadColOffset(*fPayloadCurr);
    1692         583 :     Int_t row = Row(*fPayloadCurr);
    1693         583 :     fPayloadCurr++;
    1694             : 
    1695         627 :     if ((row > 11) && (fCurrStack == 2)) {
    1696           0 :       MCMError(kInvalidPadRow, "Data in padrow > 11 for stack 2");
    1697           0 :     }
    1698             : 
    1699         583 :     if (fErrorFlags & (kDiscardHC | kDiscardDDL))
    1700           0 :       break;
    1701             : 
    1702             :     // ----- Reading ADC channels -----
    1703        1749 :     AliDebug(2, DumpAdcMask("ADC mask: ", *fPayloadCurr));
    1704             : 
    1705             :     // ----- analysing the ADC mask -----
    1706             :     channelcount = 0;
    1707         583 :     channelcountExp = GetNActiveChannelsFromMask(*fPayloadCurr);
    1708         583 :     channelcountMax = GetNActiveChannels(*fPayloadCurr);
    1709         583 :     Int_t channelmask = GetActiveChannels(*fPayloadCurr);
    1710             :     Int_t channelno = -1;
    1711         583 :     fPayloadCurr++;
    1712             : 
    1713         583 :     if (channelcountExp != channelcountMax) {
    1714           0 :       if (channelcountExp > channelcountMax) {
    1715             :         Int_t temp = channelcountExp;
    1716             :         channelcountExp = channelcountMax;
    1717             :         channelcountMax = temp;
    1718           0 :       }
    1719           0 :       while (channelcountExp < channelcountMax && channelcountExp < 21 &&
    1720           0 :              fPayloadCurr - fPayloadStart < fPayloadSize - 10 * channelcountExp - 1) {
    1721           0 :         MCMError(kAdcMaskInconsistent,
    1722             :                  "Possible MCM-H: 0x%08x, possible ADC-mask: 0x%08x",
    1723           0 :                  *(fPayloadCurr + 10 * channelcountExp),
    1724           0 :                  *(fPayloadCurr + 10 * channelcountExp + 1) );
    1725           0 :         if (!CouldBeMCMhdr( *(fPayloadCurr + 10 * channelcountExp)) && !CouldBeADCmask( *(fPayloadCurr + 10 * channelcountExp + 1)))
    1726           0 :           channelcountExp++;
    1727             :         else {
    1728             :           break;
    1729             :         }
    1730             :       }
    1731           0 :       MCMError(kAdcMaskInconsistent,
    1732             :                "Inconsistency in no. of active channels: Counter: %i, Mask: %i, chosen: %i!",
    1733           0 :                GetNActiveChannels(fPayloadCurr[-1]), GetNActiveChannelsFromMask(fPayloadCurr[-1]), channelcountExp);
    1734           0 :     }
    1735        1749 :     AliDebug(2, Form("expecting %i active channels, %i timebins", channelcountExp, fCurrNtimebins));
    1736             : 
    1737             :     // ----- reading marked ADC channels -----
    1738       11986 :     while (channelcount < channelcountExp && *(fPayloadCurr) != fgkDataEndmarker) {
    1739        3801 :       if (channelno < 20)
    1740        3801 :         channelno++;
    1741       20610 :       while (channelno < 20 && (channelmask & 1 << channelno) == 0)
    1742        4385 :         channelno++;
    1743             : 
    1744        3801 :       if (fCurrNtimebins > 30) {
    1745           0 :         currentTimebin = ((*fPayloadCurr >> 2) & 0x3f);
    1746           0 :         timebins = ((*fPayloadCurr >> 8) & 0xf) * 3;
    1747           0 :       }
    1748             :       else {
    1749             :         currentTimebin = 0;
    1750             :       }
    1751             : 
    1752             :       adcwc = 0;
    1753        3801 :       Int_t nADCwords = (timebins + 2) / 3;
    1754       11403 :       AliDebug(3, Form("Now reading %i words for channel %2i", nADCwords, channelno));
    1755        3801 :       Int_t adccol = adccoloff - channelno;
    1756        3801 :       Int_t padcol = padcoloff - channelno;
    1757             : //      if (adccol < 3 || adccol > 165)
    1758             : //      AliInfo(Form("writing channel %i of det %3i %i:%2i to adcrow/-col: %i/%i padcol: %i",
    1759             : //                   channelno, fCurrHC/2, fCurrRobPos, fCurrMcmPos, row, adccol, padcol));
    1760             : 
    1761      110229 :       while ((adcwc < nADCwords) &&
    1762       34209 :              (*(fPayloadCurr) != fgkDataEndmarker) &&
    1763       34209 :              (fPayloadCurr - fPayloadStart < fPayloadSize)) {
    1764       34209 :         int check = 0x3 & *fPayloadCurr;
    1765       34209 :         if (channelno % 2 != 0) { // odd channel
    1766       16524 :           if (check != 0x2 && channelno < 21) {
    1767           0 :             MCMError(kAdcCheckInvalid,
    1768             :                      "%i for %2i. ADC word in odd channel %i",
    1769           0 :                      check, adcwc+1, channelno);
    1770           0 :           }
    1771             :         }
    1772             :         else {                  // even channel
    1773       17685 :           if (check != 0x3 && channelno < 21) {
    1774           0 :             MCMError(kAdcCheckInvalid,
    1775             :                      "%i for %2i. ADC word in even channel %i",
    1776           0 :                      check, adcwc+1, channelno);
    1777           0 :           }
    1778             :         }
    1779             : 
    1780       34209 :         if ((fErrorFlags & kDiscardMCM) == 0) {
    1781             :           // filling the actual timebin data
    1782       34209 :           int tb2 = 0x3ff & (*fPayloadCurr >> 22);
    1783       34209 :           int tb1 = 0x3ff & (*fPayloadCurr >> 12);
    1784       34209 :           int tb0 = 0x3ff & (*fPayloadCurr >>  2);
    1785       38010 :           if (adcwc != 0 || fCurrNtimebins <= 30)
    1786       34209 :             fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
    1787             :           else
    1788             :             tb0 = -1;
    1789       34209 :           if (currentTimebin < fCurrNtimebins)
    1790       34209 :             fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
    1791       34209 :           if (currentTimebin < fCurrNtimebins)
    1792       34209 :             fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
    1793       34209 :         }
    1794             : 
    1795       34209 :         adcwc++;
    1796       34209 :         fPayloadCurr++;
    1797             :       }
    1798             : 
    1799        3801 :       if (adcwc != nADCwords)
    1800           0 :         MCMError(kAdcDataAbort);
    1801             : 
    1802             :       // adding index
    1803        3801 :       if (padcol > 0 && padcol < 144) {
    1804        3767 :         fSignalIndex->AddIndexRC(row, padcol);
    1805        3767 :       }
    1806             : 
    1807        3801 :       channelcount++;
    1808             :     }
    1809             : 
    1810        1166 :     if (fCurrSm > -1 && fCurrSm < 18) {
    1811         583 :       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNChannels += channelcount;
    1812         583 :       fStats.fStatsSector[fCurrSm].fNChannels                      += channelcount;
    1813         583 :     }
    1814         583 :     if (channelcount != channelcountExp)
    1815           0 :       MCMError(kAdcChannelsMiss);
    1816             : 
    1817         583 :     mcmcount++;
    1818        1166 :     if (fCurrSm > -1 && fCurrSm < 18) {
    1819         583 :       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNMCMs++;
    1820         583 :       fStats.fStatsSector[fCurrSm].fNMCMs++;
    1821         583 :     }
    1822             : 
    1823         583 :     if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
    1824           0 :       AliInfo(DumpRaw(Form("Event %i: Det %3i ROB %i MCM %2i", fRawReader->GetEventIndex(), fCurrHC/2, fCurrRobPos, fCurrMcmPos),
    1825             :                       startPosMCM, fPayloadCurr - startPosMCM));
    1826           0 :     }
    1827             : 
    1828             :     // continue with next MCM
    1829         583 :   }
    1830             : 
    1831             :   // check for missing MCMs (if header suppression is inactive)
    1832        4320 :   if (((fCurrMajor & 0x1) == 0) && (mcmcount != mcmcountExp)) {
    1833           0 :     LinkError(kMissMcmHeaders,
    1834             :               "No. of MCM headers %i not as expected: %i",
    1835             :               mcmcount, mcmcountExp);
    1836           0 :   }
    1837             : 
    1838        4320 :   return (fPayloadCurr - start);
    1839           0 : }
    1840             : 
    1841             : Int_t AliTRDrawStream::ReadNonZSData()
    1842             : {
    1843             :   // read the non-zs data from one link from the current reading position
    1844             : 
    1845           0 :   UInt_t *start = fPayloadCurr;
    1846             : 
    1847             :   Int_t mcmcount = 0;
    1848           0 :   Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
    1849             :   Int_t channelcount = 0;
    1850             :   Int_t channelcountExp = 0;
    1851             :   Int_t timebins;
    1852             :   Int_t currentTimebin = 0;
    1853             :   Int_t adcwc = 0;
    1854             :   Int_t evno = -1;
    1855             :   Int_t lastmcmpos = -1;
    1856             :   Int_t lastrobpos = -1;
    1857             : 
    1858           0 :   if (fCurrNtimebins != fNtimebins) {
    1859           0 :     if (fNtimebins > 0)
    1860           0 :       LinkError(kNtimebinsChanged,
    1861             :                 "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
    1862           0 :     fNtimebins = fCurrNtimebins;
    1863           0 :   }
    1864             : 
    1865           0 :   timebins = fNtimebins;
    1866             : 
    1867           0 :   while (*(fPayloadCurr) != fgkDataEndmarker &&
    1868           0 :          fPayloadCurr - fPayloadStart < fPayloadSize - 2) {
    1869             : 
    1870             :     // ----- Checking MCM Header -----
    1871           0 :     AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
    1872             : 
    1873             :     // ----- checking for proper readout order - ROB -----
    1874           0 :     fCurrRobPos = ROB(*fPayloadCurr);
    1875           0 :     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
    1876           0 :       if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
    1877           0 :         lastmcmpos = -1;
    1878           0 :       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
    1879           0 :     }
    1880             :     else {
    1881           0 :       ROBError(kPosUnexp, Form("#%i after #%i in readout order", GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos));
    1882             :     }
    1883             : 
    1884             :     // ----- checking for proper readout order - MCM -----
    1885           0 :     fCurrMcmPos = MCM(*fPayloadCurr);
    1886           0 :     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
    1887           0 :       lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
    1888           0 :     }
    1889             :     else {
    1890           0 :       MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
    1891             :     }
    1892             : 
    1893           0 :     if (EvNo(*fPayloadCurr) != (evno & 0xfffff)) {
    1894           0 :       if (evno == -1) {
    1895           0 :         evno = EvNo(*fPayloadCurr);
    1896           0 :       }
    1897             :       else {
    1898           0 :         MCMError(kEvCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
    1899             : #ifdef TRD_RAW_DEBUG
    1900             :         if (fCurrL0offset[fCurrHC/2] != 0)
    1901             :           LinkError(kEvCntMismatch, "offset for %i %i %i changed from %i to %i = %i - %i",
    1902             :                     fCurrEquipmentId, fCurrSlot, fCurrLink/2, fCurrL0offset[fCurrHC/2],
    1903             :                     EvNo(*fPayloadCurr) - fCurrL0Count[fCurrEquipmentId-kDDLOffset],
    1904             :                     EvNo(*fPayloadCurr), fCurrL0Count[fCurrEquipmentId-kDDLOffset]);
    1905             :         fCurrL0offset[fCurrHC/2] = EvNo(*fPayloadCurr) - fCurrL0Count[fCurrEquipmentId-kDDLOffset];
    1906             :         evno = fCurrL0Count[fCurrEquipmentId-kDDLOffset] + fCurrL0offset[fCurrHC/2];
    1907             : #endif
    1908             :       }
    1909             :     }
    1910             : 
    1911             :     channelcount = 0;
    1912             :     channelcountExp = 21;
    1913             :     int channelno = -1;
    1914             : 
    1915           0 :     Int_t adccoloff = AdcColOffset(*fPayloadCurr);
    1916           0 :     Int_t padcoloff = PadColOffset(*fPayloadCurr);
    1917           0 :     Int_t row = Row(*fPayloadCurr);
    1918           0 :     fPayloadCurr++;
    1919             : 
    1920           0 :     if ((row > 11) && (fCurrStack == 2)) {
    1921           0 :       MCMError(kInvalidPadRow, "Data in padrow > 11 for stack 2");
    1922           0 :     }
    1923             : 
    1924           0 :     if (fErrorFlags & (kDiscardHC | kDiscardDDL))
    1925           0 :       break;
    1926             : 
    1927             :     // ----- reading marked ADC channels -----
    1928           0 :     while (channelcount < channelcountExp &&
    1929           0 :            *(fPayloadCurr) != fgkDataEndmarker) {
    1930           0 :       if (channelno < 20)
    1931           0 :         channelno++;
    1932             : 
    1933             :       currentTimebin = 0;
    1934             : 
    1935             :       adcwc = 0;
    1936           0 :       Int_t nADCwords = (timebins + 2) / 3;
    1937           0 :       AliDebug(2, Form("Now looking %i words", nADCwords));
    1938           0 :       Int_t adccol = adccoloff - channelno;
    1939           0 :       Int_t padcol = padcoloff - channelno;
    1940           0 :       while ((adcwc < nADCwords) &&
    1941           0 :              (*(fPayloadCurr) != fgkDataEndmarker) &&
    1942           0 :              (fPayloadCurr - fPayloadStart < fPayloadSize)) {
    1943           0 :         int check = 0x3 & *fPayloadCurr;
    1944           0 :         if (channelno % 2 != 0) { // odd channel
    1945           0 :           if (check != 0x2 && channelno < 21) {
    1946           0 :             MCMError(kAdcCheckInvalid,
    1947             :                      "%i for %2i. ADC word in odd channel %i",
    1948           0 :                      check, adcwc+1, channelno);
    1949           0 :           }
    1950             :         }
    1951             :         else {                  // even channel
    1952           0 :           if (check != 0x3 && channelno < 21) {
    1953           0 :             MCMError(kAdcCheckInvalid,
    1954             :                      "%i for %2i. ADC word in even channel %i",
    1955           0 :                      check, adcwc+1, channelno);
    1956           0 :           }
    1957             :         }
    1958             : 
    1959           0 :         if ((fErrorFlags & kDiscardMCM) == 0) {
    1960             :           // filling the actual timebin data
    1961           0 :           int tb2 = 0x3ff & (*fPayloadCurr >> 22);
    1962           0 :           int tb1 = 0x3ff & (*fPayloadCurr >> 12);
    1963           0 :           int tb0 = 0x3ff & (*fPayloadCurr >>  2);
    1964           0 :           if (adcwc != 0 || fCurrNtimebins <= 30)
    1965           0 :             fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
    1966             :           else
    1967             :             tb0 = -1;
    1968           0 :           if (currentTimebin < fCurrNtimebins)
    1969           0 :             fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
    1970           0 :           if (currentTimebin < fCurrNtimebins)
    1971           0 :             fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
    1972           0 :         }
    1973             : 
    1974           0 :         adcwc++;
    1975           0 :         fPayloadCurr++;
    1976             :       }
    1977             : 
    1978           0 :       if (adcwc != nADCwords)
    1979           0 :         MCMError(kAdcDataAbort);
    1980             : 
    1981             :       // adding index
    1982           0 :       if (padcol > 0 && padcol < 144) {
    1983           0 :         fSignalIndex->AddIndexRC(row, padcol);
    1984           0 :       }
    1985             : 
    1986           0 :       channelcount++;
    1987             :     }
    1988             : 
    1989           0 :     if (channelcount != channelcountExp)
    1990           0 :       MCMError(kAdcChannelsMiss);
    1991           0 :     mcmcount++;
    1992             :     // continue with next MCM
    1993           0 :   }
    1994             : 
    1995             :   // check for missing MCMs (if header suppression is inactive)
    1996           0 :   if (mcmcount != mcmcountExp) {
    1997           0 :     LinkError(kMissMcmHeaders,
    1998             :               "%i not as expected: %i", mcmcount, mcmcountExp);
    1999           0 :   }
    2000             : 
    2001           0 :   return (fPayloadCurr - start);
    2002             : }
    2003             : 
    2004             : #ifdef TRD_RAW_CRC
    2005             : UShort_t AliTRDrawStream::CalcLinkChecksum(UInt_t *data, Int_t size)
    2006             : {
    2007             :   // calculate the CRC for the data from this link
    2008             :   // must not change the pointers to the data
    2009             : 
    2010             :   // always count two endmarkers
    2011             :   Int_t nEndmarkers = 0;
    2012             :   for (Int_t i = 0; i < size; i++) {
    2013             :     if (data[size-1 - i] != fgkDataEndmarker)
    2014             :       break;
    2015             :     nEndmarkers++;
    2016             :   }
    2017             : 
    2018             :   size = size - (nEndmarkers-2);
    2019             : 
    2020             :   boost::crc_optimal<16, 0x8005, 0, 0, false, false> checksumLink;
    2021             : 
    2022             :   checksumLink.reset();
    2023             :   checksumLink.process_bytes(data, size*sizeof(UInt_t));
    2024             :   return checksumLink();
    2025             : }
    2026             : #else
    2027             : UShort_t AliTRDrawStream::CalcLinkChecksum(UInt_t * /* data */, Int_t /* size */)
    2028             : {
    2029             :   // checksum calculation relies on boost,
    2030             :   // we return 0 if we cannot calculate it
    2031             : 
    2032           0 :   AliError("Checksum calculation relies on boost CRC implementation!");
    2033             : 
    2034           0 :   return 0;
    2035             : }
    2036             : #endif
    2037             : 
    2038             : Int_t AliTRDrawStream::SeekNextStack()
    2039             : {
    2040             :   // proceed in raw data stream till the next stack
    2041             : 
    2042         720 :   if (!fCurrStackEndmarkerAvail)
    2043         360 :     return 0;
    2044             : 
    2045           0 :   UInt_t *start = fPayloadCurr;
    2046             : 
    2047             :   // read until data endmarkers
    2048           0 :   while ((fPayloadCurr - fPayloadStart < fPayloadSize-1) &&
    2049           0 :          ((fPayloadCurr[0] != fgkStackEndmarker[0]) ||
    2050           0 :           (fPayloadCurr[1] != fgkStackEndmarker[1])))
    2051           0 :     fPayloadCurr++;
    2052             : 
    2053           0 :   if ((fPayloadCurr - start) != 0)
    2054           0 :     StackError(kUnknown, "skipped %i words to reach stack endmarker", fPayloadCurr - start);
    2055             : 
    2056           0 :   AliDebug(2, Form("stack endmarker: 0x%08x 0x%08x", fPayloadCurr[0], fPayloadCurr[1]));
    2057             : 
    2058             :   // goto next stack
    2059           0 :   fPayloadCurr++;
    2060           0 :   fPayloadCurr++;
    2061             : 
    2062           0 :   return (fPayloadCurr-start);
    2063         360 : }
    2064             : 
    2065             : Int_t AliTRDrawStream::SeekNextLink()
    2066             : {
    2067             :   // proceed in raw data stream till the next link
    2068             : 
    2069        8640 :   UInt_t *start = fPayloadCurr;
    2070             : 
    2071             :   // read until data endmarkers
    2072       12960 :   while (fPayloadCurr - fPayloadStart < fPayloadSize &&
    2073        4320 :          ((fPayloadCurr[0] != fgkStackEndmarker[0]) ||
    2074           0 :           (fPayloadCurr[1] != fgkStackEndmarker[1])) &&
    2075        4320 :          *fPayloadCurr != fgkDataEndmarker)
    2076           0 :     fPayloadCurr++;
    2077             : 
    2078             :   // read all data endmarkers
    2079       60480 :   while (fPayloadCurr - fPayloadStart < fPayloadSize &&
    2080       21528 :          *fPayloadCurr == fgkDataEndmarker)
    2081       38880 :     fPayloadCurr++;
    2082             : 
    2083        4320 :   return (fPayloadCurr - start);
    2084             : }
    2085             : 
    2086             : 
    2087             : void AliTRDrawStream::EquipmentError(ErrorCode_t err, const char *const msg, ...)
    2088             : {
    2089             :   // register error according to error code on equipment level
    2090             :   // and return the corresponding error message
    2091             : 
    2092           0 :   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
    2093           0 :   fLastError.fStack  = -1;
    2094           0 :   fLastError.fLink   = -1;
    2095           0 :   fLastError.fRob    = -1;
    2096           0 :   fLastError.fMcm    = -1;
    2097           0 :   fLastError.fError  = err;
    2098           0 :   (this->*fStoreError)();
    2099             : 
    2100           0 :   va_list ap;
    2101           0 :   if (fgErrorDebugLevel[err] > 10)
    2102           0 :     AliDebug(fgErrorDebugLevel[err],
    2103             :              Form("Event %6i: Eq. %2d - %s : %s",
    2104             :                   fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
    2105             :                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
    2106             :   else
    2107           0 :     AliError(Form("Event %6i: Eq. %2d - %s : %s",
    2108             :                   fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
    2109             :                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
    2110           0 :   fErrorFlags |= fgErrorBehav[err];
    2111           0 : }
    2112             : 
    2113             : 
    2114             : void AliTRDrawStream::StackError(ErrorCode_t err, const char *const msg, ...)
    2115             : {
    2116             :   // register error according to error code on stack level
    2117             :   // and return the corresponding error message
    2118             : 
    2119           0 :   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
    2120           0 :   fLastError.fStack  = fCurrSlot;
    2121           0 :   fLastError.fLink   = -1;
    2122           0 :   fLastError.fRob    = -1;
    2123           0 :   fLastError.fMcm    = -1;
    2124           0 :   fLastError.fError  = err;
    2125           0 :   (this->*fStoreError)();
    2126             : 
    2127           0 :   va_list ap;
    2128           0 :   if (fgErrorDebugLevel[err] > 0)
    2129           0 :     AliDebug(fgErrorDebugLevel[err],
    2130             :              Form("Event %6i: Eq. %2d S %i - %s : %s",
    2131             :                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
    2132             :                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
    2133             :   else
    2134           0 :     AliError(Form("Event %6i: Eq. %2d S %i - %s : %s",
    2135             :                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
    2136             :                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
    2137           0 :   fErrorFlags |= fgErrorBehav[err];
    2138           0 : }
    2139             : 
    2140             : 
    2141             : void AliTRDrawStream::LinkError(ErrorCode_t err, const char *const msg, ...)
    2142             : {
    2143             :   // register error according to error code on link level
    2144             :   // and return the corresponding error message
    2145             : 
    2146           0 :   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
    2147           0 :   fLastError.fStack  = fCurrSlot;
    2148           0 :   fLastError.fLink   = fCurrLink;
    2149           0 :   fLastError.fRob    = -1;
    2150           0 :   fLastError.fMcm    = -1;
    2151           0 :   fLastError.fError  = err;
    2152           0 :   (this->*fStoreError)();
    2153             : 
    2154           0 :   va_list ap;
    2155           0 :   if (fgErrorDebugLevel[err] > 0)
    2156           0 :     AliDebug(fgErrorDebugLevel[err],
    2157             :              Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
    2158             :                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
    2159             :                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
    2160             :   else
    2161           0 :     AliError(Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
    2162             :                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
    2163             :                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
    2164           0 :   fErrorFlags |= fgErrorBehav[err];
    2165           0 : }
    2166             : 
    2167             : 
    2168             : void AliTRDrawStream::ROBError(ErrorCode_t err, const char *const msg, ...)
    2169             : {
    2170             :   // register error according to error code on ROB level
    2171             :   // and return the corresponding error message
    2172             : 
    2173           0 :   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
    2174           0 :   fLastError.fStack  = fCurrSlot;
    2175           0 :   fLastError.fLink   = fCurrLink;
    2176           0 :   fLastError.fRob    = fCurrRobPos;
    2177           0 :   fLastError.fMcm    = -1;
    2178           0 :   fLastError.fError  = err;
    2179           0 :   (this->*fStoreError)();
    2180             : 
    2181           0 :   va_list ap;
    2182           0 :   if (fgErrorDebugLevel[err] > 0)
    2183           0 :     AliDebug(fgErrorDebugLevel[err],
    2184             :              Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
    2185             :                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
    2186             :                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
    2187             :   else
    2188           0 :     AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
    2189             :                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
    2190             :                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
    2191           0 :   fErrorFlags |= fgErrorBehav[err];
    2192           0 : }
    2193             : 
    2194             : 
    2195             : void AliTRDrawStream::MCMError(ErrorCode_t err, const char *const msg, ...)
    2196             : {
    2197             :   // register error according to error code on MCM level
    2198             :   // and return the corresponding error message
    2199             : 
    2200           0 :   fLastError.fSector = fCurrEquipmentId - kDDLOffset;
    2201           0 :   fLastError.fStack  = fCurrSlot;
    2202           0 :   fLastError.fLink   = fCurrLink;
    2203           0 :   fLastError.fRob    = fCurrRobPos;
    2204           0 :   fLastError.fMcm    = fCurrMcmPos;
    2205           0 :   fLastError.fError  = err;
    2206           0 :   (this->*fStoreError)();
    2207             : 
    2208           0 :   va_list ap;
    2209           0 :   if (fgErrorDebugLevel[err] > 0)
    2210           0 :     AliDebug(fgErrorDebugLevel[err],
    2211             :              Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
    2212             :                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
    2213             :                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
    2214             :   else
    2215           0 :     AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
    2216             :                   fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
    2217             :                   (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
    2218           0 :   fErrorFlags |= fgErrorBehav[err];
    2219           0 : }
    2220             : 
    2221             : const char* AliTRDrawStream::GetErrorMessage(ErrorCode_t errCode)
    2222             : {
    2223             :   // return the error message for the given error code
    2224             : 
    2225           0 :   if (errCode > 0 && errCode < kLastErrorCode)
    2226           0 :     return fgkErrorMessages[errCode];
    2227             :   else
    2228           0 :     return "";
    2229           0 : }
    2230             : 
    2231             : void AliTRDrawStream::AliTRDrawStats::ClearStats()
    2232             : {
    2233             :   // clear statistics (includes clearing sector-wise statistics)
    2234             : 
    2235           0 :   fBytesRead = 0;
    2236           0 :   for (Int_t iSector = 0; iSector < 18; iSector++) {
    2237           0 :     fStatsSector[iSector].ClearStats();
    2238             :   }
    2239             : 
    2240           0 : }
    2241             : 
    2242             : void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::ClearStats()
    2243             : {
    2244             :   // clear statistics (includes clearing HC-wise statistics)
    2245             : 
    2246           0 :   fBytes = 0;
    2247           0 :   fBytesRead = 0;
    2248           0 :   fNTracklets = 0;
    2249           0 :   fNMCMs = 0;
    2250           0 :   fNChannels = 0;
    2251             : 
    2252           0 :   for (Int_t iHC = 0; iHC < 60; iHC++) {
    2253           0 :     fStatsHC[iHC].ClearStats();
    2254             :   }
    2255           0 : }
    2256             : 
    2257             : void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::AliTRDrawStatsHC::ClearStats()
    2258             : {
    2259             :   // clear statistics
    2260             : 
    2261           0 :   fBytes = 0;
    2262           0 :   fBytesRead = 0;
    2263           0 :   fNTracklets = 0;
    2264           0 :   fNMCMs = 0;
    2265           0 :   fNChannels = 0;
    2266           0 : }
    2267             : 
    2268             : void AliTRDrawStream::SetDumpMCM(Int_t det, Int_t rob, Int_t mcm, Bool_t dump)
    2269             : {
    2270             :   // mark MCM for dumping of raw data
    2271             : 
    2272           0 :   if (dump) {
    2273           0 :     fDumpMCM[fNDumpMCMs++] = (det << 7) | (rob << 4) | mcm;
    2274           0 :   }
    2275             :   else {
    2276             :     Int_t iMCM;
    2277           0 :     for (iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
    2278           0 :       if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
    2279           0 :         fNDumpMCMs--;
    2280           0 :         break;
    2281             :       }
    2282             :     }
    2283           0 :     for ( ; iMCM < fNDumpMCMs; iMCM++) {
    2284           0 :       fDumpMCM[iMCM] = fDumpMCM[iMCM+1];
    2285             :     }
    2286             :   }
    2287           0 : }
    2288             : 
    2289             : Bool_t AliTRDrawStream::DumpingMCM(Int_t det, Int_t rob, Int_t mcm)  const
    2290             : {
    2291             :   // check if MCM data should be dumped
    2292             : 
    2293           0 :   for (Int_t iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
    2294           0 :     if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
    2295           0 :       return kTRUE;
    2296             :     }
    2297             :   }
    2298           0 :   return kFALSE;
    2299           0 : }
    2300             : 
    2301             : TString AliTRDrawStream::DumpRaw(TString title, const UInt_t *start, Int_t length, UInt_t endmarker)
    2302             : {
    2303             :   // dump raw data
    2304             : 
    2305           0 :   title += "\n";
    2306           0 :   for (Int_t pos = 0; pos < length; pos += 4) {
    2307           0 :     if ((start[pos+0] != endmarker) && pos+0 < length)
    2308           0 :       if ((start[pos+1] != endmarker && pos+1 < length))
    2309           0 :         if ((start[pos+2] != endmarker && pos+2 < length))
    2310           0 :           if ((start[pos+3] != endmarker && pos+3 < length))
    2311           0 :             title += Form("   0x%08x 0x%08x 0x%08x 0x%08x\n",
    2312             :                           start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
    2313             :           else {
    2314           0 :             title += Form("   0x%08x 0x%08x 0x%08x 0x%08x\n",
    2315           0 :                           start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
    2316           0 :             return title;
    2317             :           }
    2318             :         else {
    2319           0 :           title += Form("   0x%08x 0x%08x 0x%08x\n",
    2320           0 :                         start[pos+0], start[pos+1], start[pos+2]);
    2321           0 :           return title;
    2322             :         }
    2323             :       else {
    2324           0 :         title += Form("   0x%08x 0x%08x\n",
    2325           0 :                       start[pos+0], start[pos+1]);
    2326           0 :         return title;
    2327             :       }
    2328             :     else {
    2329           0 :       title += Form("   0x%08x\n",
    2330           0 :                     start[pos+0]);
    2331           0 :       return title;
    2332             :     }
    2333             :   }
    2334           0 :   return title;
    2335           0 : }
    2336             : 
    2337             : TString AliTRDrawStream::DumpMcmHeader(TString title, UInt_t word)
    2338             : {
    2339           0 :   title += Form("0x%08x -> ROB: %i, MCM: %2i",
    2340           0 :                 word, ROB(word), MCM(word));
    2341           0 :   return title;
    2342             : }
    2343             : 
    2344             : TString AliTRDrawStream::DumpAdcMask(TString title, UInt_t word)
    2345             : {
    2346           0 :   title += Form("0x%08x -> #ch : %2i, 0x%06x (%2i ch)",
    2347           0 :                 word, GetNActiveChannels(word), GetActiveChannels(word), GetNActiveChannelsFromMask(word));
    2348           0 :   return title;
    2349             : }
    2350             : 
    2351           2 : AliTRDrawStream::AliTRDrawStreamError::AliTRDrawStreamError(Int_t error, Int_t sector, Int_t stack, Int_t link, Int_t rob, Int_t mcm) :
    2352           2 :   fError(error),
    2353           2 :   fSector(sector),
    2354           2 :   fStack(stack),
    2355           2 :   fLink(link),
    2356           2 :   fRob(rob),
    2357           2 :   fMcm(mcm)
    2358          10 : {
    2359             :   // ctor
    2360             : 
    2361           4 : }
    2362             : 
    2363             : void AliTRDrawStream::SortTracklets(TClonesArray *trklArray, TList &sortedTracklets, Int_t *indices)
    2364             : {
    2365             :   // sort tracklets for referencing from GTU tracks
    2366             : 
    2367          16 :   if (!trklArray)
    2368             :     return;
    2369             : 
    2370           8 :   Int_t nTracklets = trklArray->GetEntriesFast();
    2371             : 
    2372             :   Int_t lastHC = -1;
    2373        1454 :   for (Int_t iTracklet = 0; iTracklet < nTracklets; iTracklet++) {
    2374         719 :     AliTRDtrackletBase *trkl = (AliTRDtrackletBase*) ((*trklArray)[iTracklet]);
    2375         719 :     Int_t hc = trkl->GetHCId();
    2376         719 :     if ((hc < 0) || (hc >= 1080)) {
    2377           0 :       AliErrorClass(Form("HC for tracklet: 0x%08x out of range: %i", trkl->GetTrackletWord(), trkl->GetHCId()));
    2378           0 :       continue;
    2379             :     }
    2380        2157 :     AliDebugClass(5, Form("hc: %4i : 0x%08x z: %2i", hc, trkl->GetTrackletWord(), trkl->GetZbin()));
    2381         719 :     if (hc != lastHC) {
    2382         987 :       AliDebugClass(2, Form("set tracklet index for HC %i to %i", hc, iTracklet));
    2383         329 :       indices[hc] = iTracklet + 1;
    2384             :       lastHC = hc;
    2385         329 :     }
    2386         719 :   }
    2387             : 
    2388        8656 :   for (Int_t iDet = 0; iDet < 540; iDet++) {
    2389        4320 :     Int_t trklIndexA = indices[2*iDet + 0] - 1;
    2390        4320 :     Int_t trklIndexB = indices[2*iDet + 1] - 1;
    2391        4320 :     Int_t trklIndex  = sortedTracklets.GetEntries();
    2392        8827 :     AliTRDtrackletBase *trklA = trklIndexA > -1 ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
    2393        8782 :     AliTRDtrackletBase *trklB = trklIndexB > -1 ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
    2394             :     AliTRDtrackletBase *trklNext = 0x0;
    2395        9359 :     while (trklA != 0x0 || trklB != 0x0) {
    2396        2157 :       AliDebugClass(5, Form("det %i - A: %i/%i -> %p, B: %i/%i -> %p",
    2397             :                        iDet, trklIndexA, nTracklets, trklA, trklIndexB, nTracklets, trklB));
    2398         719 :       if (trklA == 0x0) {
    2399             :         trklNext = trklB;
    2400         329 :         trklIndexB++;
    2401         987 :         trklB = trklIndexB < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
    2402         658 :         if (trklB && trklB->GetHCId() != 2*iDet + 1)
    2403         130 :           trklB = 0x0;
    2404             :       }
    2405         390 :       else if (trklB == 0x0) {
    2406             :         trklNext = trklA;
    2407         272 :         trklIndexA++;
    2408         808 :         trklA = trklIndexA < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
    2409         536 :         if (trklA && trklA->GetHCId() != 2*iDet)
    2410         163 :           trklA = 0x0;
    2411             :       }
    2412             :       else {
    2413         118 :         if (trklA->GetZbin() <= trklB->GetZbin()) {
    2414             :           trklNext = trklA;
    2415          41 :           trklIndexA++;
    2416         123 :           trklA = trklIndexA < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
    2417          82 :           if (trklA && trklA->GetHCId() != 2*iDet)
    2418          16 :             trklA = 0x0;
    2419             :         }
    2420             :         else {
    2421             :           trklNext = trklB;
    2422          77 :           trklIndexB++;
    2423         231 :           trklB = trklIndexB < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
    2424         154 :           if (trklB && trklB->GetHCId() != 2*iDet + 1)
    2425          12 :             trklB = 0x0;
    2426             :         }
    2427             :       }
    2428         719 :       if (trklNext) {
    2429         719 :         sortedTracklets.Add(trklNext);
    2430             : 
    2431         719 :       }
    2432             :     }
    2433             : 
    2434             :     // updating tracklet indices as in output
    2435        4320 :     if (sortedTracklets.GetEntries() != trklIndex) {
    2436         301 :       indices[2*iDet + 0] = trklIndex;
    2437         301 :       indices[2*iDet + 1] = sortedTracklets.GetEntries();
    2438         301 :     } else {
    2439        4019 :       indices[2*iDet + 0] = indices[2*iDet + 1] = -1;
    2440             :     }
    2441             :   }
    2442          16 : }
    2443             : 
    2444             : void AliTRDrawStream::AssignTracklets(AliESDTrdTrack *trdTrack, Int_t *trackletIndex, Int_t refIndex[6])
    2445             : {
    2446        4638 :   UInt_t mask  = trdTrack->GetLayerMask();
    2447        2319 :   UInt_t stack = trdTrack->GetStack();
    2448             : 
    2449       32466 :   for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
    2450       13914 :     refIndex[iLayer] = -1;
    2451             : 
    2452       13914 :     if (mask & (1 << iLayer)) {
    2453             : 
    2454          73 :       Int_t det = trdTrack->GetSector()*30 + stack*6 + iLayer;
    2455          73 :       Int_t idx = trdTrack->GetTrackletIndex(iLayer);
    2456             : 
    2457         146 :       if ((det < 0) || (det > 539)) {
    2458          73 :         AliErrorClass(Form("Invalid detector no. from track: %i", 2*det));
    2459           0 :         continue;
    2460             :       }
    2461          73 :       if (trackletIndex[2*det] >= 0) {
    2462         146 :         if ((trackletIndex[2*det] + idx > -1) &&
    2463          73 :             (trackletIndex[2*det] + idx < trackletIndex[2*det+1])) {
    2464          73 :           refIndex[iLayer] = trackletIndex[2*det] + idx;
    2465          73 :         } else {
    2466           0 :           AliErrorClass(Form("Requested tracklet index %i out of range", idx));
    2467             :         }
    2468             :       } else {
    2469           0 :         AliErrorClass(Form("Non-existing tracklets requested in det %i", det));
    2470             :       }
    2471          73 :     }
    2472             :   }
    2473        2319 : }

Generated by: LCOV version 1.11