]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - TRD/AliTRDrawStream.cxx
Merge branch 'master' of https://git.cern.ch/reps/AliRoot
[u/mrichter/AliRoot.git] / TRD / AliTRDrawStream.cxx
index 293eeb89bb3c3706079b867add803b3b556d53d5..cf31acaa159fd66293e67074a30dfe73ca1f9d23 100644 (file)
 ////////////////////////////////////////////////////////////////////////////
 //                                                                        //
 //  Decoding data from the TRD raw stream                                 //
 ////////////////////////////////////////////////////////////////////////////
 //                                                                        //
 //  Decoding data from the TRD raw stream                                 //
-//  and translation into ADC values                                       //
+//  and translation into ADC values, on-line tracklets and tracks         //
+//                                                                        //
+//  CRC checks rely on boost, and are enabled only when TRD_RAW_CRC       //
+//  is defined                                                            //
+//                                                                        //
+//  Additional debug features can be enabled by defining TRD_RAW_DEBUG    //
 //                                                                        //
 //  Author: J. Klein (jochen.klein@cern.ch)                               //
 //                                                                        //
 ////////////////////////////////////////////////////////////////////////////
 
 //                                                                        //
 //  Author: J. Klein (jochen.klein@cern.ch)                               //
 //                                                                        //
 ////////////////////////////////////////////////////////////////////////////
 
+#include <cstdio>
+#include <cstdarg>
+
+#if defined(TRD_RAW_CRC)
+#include <boost/crc.hpp>
+#endif
+
 #include "TClonesArray.h"
 #include "TTree.h"
 
 #include "AliLog.h"
 #include "AliRawReader.h"
 #include "TClonesArray.h"
 #include "TTree.h"
 
 #include "AliLog.h"
 #include "AliRawReader.h"
+#include "AliTRDcalibDB.h"
 #include "AliTRDdigitsManager.h"
 #include "AliTRDdigitsParam.h"
 #include "AliTRDdigitsManager.h"
 #include "AliTRDdigitsParam.h"
+#include "AliTRDcalibDB.h"
+#include "AliTRDmcmSim.h"
 #include "AliTRDtrapConfig.h"
 #include "AliTRDarrayADC.h"
 #include "AliTRDarrayDictionary.h"
 #include "AliTRDSignalIndex.h"
 #include "AliTRDtrackletWord.h"
 #include "AliTRDtrapConfig.h"
 #include "AliTRDarrayADC.h"
 #include "AliTRDarrayDictionary.h"
 #include "AliTRDSignalIndex.h"
 #include "AliTRDtrackletWord.h"
-#include "AliTreeLoader.h"
+#include "AliTRDtrackletMCM.h"
+#include "AliESDTrdTrack.h"
 
 #include "AliTRDrawStream.h"
 
 
 #include "AliTRDrawStream.h"
 
-// temporary
-#include "AliRunLoader.h"
-
 ClassImp(AliTRDrawStream)
 
 ClassImp(AliTRDrawStream)
 
-// some static information 
-const Int_t AliTRDrawStream::fgkMcmOrder[] = {12, 13, 14, 15, 
-                                             8, 9, 10, 11, 
-                                             4, 5, 6, 7, 
-                                             0, 1, 2, 3};
-const Int_t  AliTRDrawStream::fgkRobOrder [] = {0, 1, 2, 3};
+// some static information
+Int_t AliTRDrawStream::fgMcmOrder[] = {12, 13, 14, 15,
+                                      8, 9, 10, 11,
+                                      4, 5, 6, 7,
+                                      0, 1, 2, 3};
+Int_t  AliTRDrawStream::fgRobOrder [] = {0, 1, 2, 3};
 const Int_t  AliTRDrawStream::fgkNlinks = 12;
 const Int_t  AliTRDrawStream::fgkNstacks = 5;
 const Int_t  AliTRDrawStream::fgkNlinks = 12;
 const Int_t  AliTRDrawStream::fgkNstacks = 5;
+const Int_t  AliTRDrawStream::fgkNsectors = 18;
+const Int_t  AliTRDrawStream::fgkNtriggers = 12;
 const UInt_t AliTRDrawStream::fgkDataEndmarker     = 0x00000000;
 const UInt_t AliTRDrawStream::fgkTrackletEndmarker = 0x10001000;
 const UInt_t AliTRDrawStream::fgkDataEndmarker     = 0x00000000;
 const UInt_t AliTRDrawStream::fgkTrackletEndmarker = 0x10001000;
+const UInt_t AliTRDrawStream::fgkStackEndmarker[] = { 0xe0d01000, 0xe0d10000 };
 
 
-const char* AliTRDrawStream::fgErrorMessages[] = {
+const char* AliTRDrawStream::fgkErrorMessages[] = {
   "Unknown error",
   "Link monitor active",
   "Unknown error",
   "Link monitor active",
-  "Pretrigger counter mismatch",
+  "Event counter mismatch",
   "not a TRD equipment (1024-1041)",
   "Invalid Stack header",
   "Invalid detector number",
   "not a TRD equipment (1024-1041)",
   "Invalid Stack header",
   "Invalid detector number",
+  "Invalid pad row",
   "No digits could be retrieved from the digitsmanager",
   "No digits could be retrieved from the digitsmanager",
-  "HC header mismatch", 
+  "HC header mismatch",
   "HC check bits wrong",
   "Unexpected position in readout stream",
   "Invalid testpattern mode",
   "Testpattern mismatch",
   "Number of timebins changed",
   "HC check bits wrong",
   "Unexpected position in readout stream",
   "Invalid testpattern mode",
   "Testpattern mismatch",
   "Number of timebins changed",
-  "ADC mask inconsistent", 
-  "ADC check bits invalid", 
+  "ADC mask inconsistent",
+  "ADC check bits invalid",
   "Missing ADC data",
   "Missing expected ADC channels",
   "Missing ADC data",
   "Missing expected ADC channels",
-  "Missing MCM headers"
+  "Missing MCM headers",
+  "Missing TP data",
+  "CRC mismatch"
+};
+
+Int_t AliTRDrawStream::fgErrorDebugLevel[] = {
+  0,
+  0,
+  2,
+  1,
+  0,
+  1,
+  0,
+  1,
+  0,
+  1,
+  2,
+  1,
+  0,
+  1,
+  1,
+  2,
+  1,
+  1,
+  1,
+  0,
+  0
+};
+
+AliTRDrawStream::ErrorBehav_t AliTRDrawStream::fgErrorBehav[] = {
+  AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kDiscardHC,
+  AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kAbort,
+  AliTRDrawStream::kAbort,
+  AliTRDrawStream::kAbort,
+  AliTRDrawStream::kDiscardMCM,
+  AliTRDrawStream::kAbort,
+  AliTRDrawStream::kDiscardHC,
+  AliTRDrawStream::kDiscardHC,
+  AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kTolerate
 };
 
 AliTRDrawStream::AliTRDrawStream(AliRawReader *rawReader) :
 };
 
 AliTRDrawStream::AliTRDrawStream(AliRawReader *rawReader) :
-  fStats(), 
+  fStoreError(&AliTRDrawStream::ForgetError),
   fRawReader(rawReader),
   fDigitsManager(0x0),
   fDigitsParam(0x0),
   fErrors(0x0),
   fLastError(),
   fRawReader(rawReader),
   fDigitsManager(0x0),
   fDigitsParam(0x0),
   fErrors(0x0),
   fLastError(),
+  fErrorFlags(0),
+  fStats(),
   fPayloadStart(0x0),
   fPayloadCurr(0x0),
   fPayloadSize(0),
   fPayloadStart(0x0),
   fPayloadCurr(0x0),
   fPayloadSize(0),
@@ -92,21 +161,48 @@ AliTRDrawStream::AliTRDrawStream(AliRawReader *rawReader) :
   fCurrRobPos(-1),
   fCurrMcmPos(-1),
   fCurrEquipmentId(0),
   fCurrRobPos(-1),
   fCurrMcmPos(-1),
   fCurrEquipmentId(0),
-  fCurrSmuIndexHeaderSize(0),
-  fCurrSmuIndexHeaderVersion(0),
+  fCurrSmHeaderSize(0),
+  fCurrSmHeaderVersion(0),
+  fCurrTrailerReadout(0),
+  fCurrTrgHeaderAvail(0),
+  fCurrTrgHeaderReadout(0),
+  fCurrTrkHeaderAvail(0),
+  fCurrStackEndmarkerAvail(0),
+  fCurrEvType(0),
+  fCurrTriggerEnable(0),
+  fCurrTriggerFired(0),
   fCurrTrackEnable(0),
   fCurrTrackletEnable(0),
   fCurrStackMask(0),
   fCurrTrackEnable(0),
   fCurrTrackletEnable(0),
   fCurrStackMask(0),
+#ifdef TRD_RAW_DEBUG
+  fCurrL0Count(),
+  fCurrL1aCount(),
+  fCurrL1rCount(),
+  fCurrL2aCount(),
+  fCurrL2rCount(),
+  fCurrL0offset(),
+#endif
+  fCurrTrkHeaderIndexWord(0x0),
+  fCurrTrkHeaderSize(0x0),
+  fCurrTrkFlags(0x0),
+  fCurrTrgHeaderIndexWord(0x0),
+  fCurrTrgHeaderSize(0x0),
+  fCurrTrgFlags(0x0),
   fCurrStackIndexWord(0x0),
   fCurrStackHeaderSize(0x0),
   fCurrStackHeaderVersion(0x0),
   fCurrLinkMask(0x0),
   fCurrCleanCheckout(0x0),
   fCurrBoardId(0x0),
   fCurrStackIndexWord(0x0),
   fCurrStackHeaderSize(0x0),
   fCurrStackHeaderVersion(0x0),
   fCurrLinkMask(0x0),
   fCurrCleanCheckout(0x0),
   fCurrBoardId(0x0),
-  fCurrHwRev(0x0),
+  fCurrHwRev(-1),
+  fCurrHwRevTMU(0x0),
   fCurrLinkMonitorFlags(0x0),
   fCurrLinkDataTypeFlags(0x0),
   fCurrLinkDebugFlags(0x0),
   fCurrLinkMonitorFlags(0x0),
   fCurrLinkDataTypeFlags(0x0),
   fCurrLinkDebugFlags(0x0),
+  fCurrMatchFlagsSRAM(),
+  fCurrMatchFlagsPostBP(),
+  fCurrChecksumStack(),
+  fCurrChecksumSIU(0),
   fCurrSpecial(-1),
   fCurrMajor(-1),
   fCurrMinor(-1),
   fCurrSpecial(-1),
   fCurrMajor(-1),
   fCurrMinor(-1),
@@ -118,36 +214,57 @@ AliTRDrawStream::AliTRDrawStream(AliRawReader *rawReader) :
   fCurrHC(-1),
   fCurrCheck(-1),
   fCurrNtimebins(-1),
   fCurrHC(-1),
   fCurrCheck(-1),
   fCurrNtimebins(-1),
-  fCurrBC(-1),
   fCurrPtrgCnt(-1),
   fCurrPtrgPhase(-1),
   fCurrPtrgCnt(-1),
   fCurrPtrgPhase(-1),
+#ifdef TRD_RAW_DEBUG
+  fCurrBC(),
+#endif
   fNDumpMCMs(0),
   fNDumpMCMs(0),
-  fTrackletArray(0x0),
   fAdcArray(0x0),
   fSignalIndex(0x0),
   fAdcArray(0x0),
   fSignalIndex(0x0),
-  fTrackletTree(0x0)
+  fTracklets(0x0),
+  fTracks(0x0),
+  fMarkers(0x0)
 {
   // default constructor
 
 {
   // default constructor
 
-  fCurrStackIndexWord     = new UInt_t[fgkNstacks];     
-  fCurrStackHeaderSize    = new UInt_t[fgkNstacks];     
+  fCurrTrkHeaderIndexWord = new UInt_t[fgkNstacks];
+  fCurrTrkHeaderSize      = new UInt_t[fgkNstacks];
+  fCurrTrkFlags           = new ULong64_t[fgkNsectors*fgkNstacks];
+  fCurrTrgHeaderIndexWord = new UInt_t[fgkNtriggers];
+  fCurrTrgHeaderSize      = new UInt_t[fgkNtriggers];
+  fCurrTrgFlags           = new UInt_t[fgkNsectors];
+#ifdef TRD_RAW_DEBUG
+  fCurrL0Count            = new UInt_t[fgkNsectors];
+  fCurrL1aCount           = new UInt_t[fgkNsectors];
+  fCurrL1rCount           = new UInt_t[fgkNsectors];
+  fCurrL2aCount           = new UInt_t[fgkNsectors];
+  fCurrL2rCount           = new UInt_t[fgkNsectors];
+#endif
+  fCurrStackIndexWord     = new UInt_t[fgkNstacks];
+  fCurrStackHeaderSize    = new UInt_t[fgkNstacks];
   fCurrStackHeaderVersion = new UInt_t[fgkNstacks];
   fCurrStackHeaderVersion = new UInt_t[fgkNstacks];
-  fCurrLinkMask           = new UInt_t[fgkNstacks];             
-  fCurrCleanCheckout      = new UInt_t[fgkNstacks];     
-  fCurrBoardId            = new UInt_t[fgkNstacks];             
-  fCurrHwRev              = new UInt_t[fgkNstacks];             
-  fCurrLinkMonitorFlags   = new UInt_t[fgkNstacks * fgkNlinks];
+  fCurrLinkMask           = new UInt_t[fgkNstacks];
+  fCurrCleanCheckout      = new UInt_t[fgkNstacks];
+  fCurrBoardId            = new UInt_t[fgkNstacks];
+  fCurrHwRevTMU           = new UInt_t[fgkNstacks];
+  fCurrLinkMonitorFlags   = new UInt_t[fgkNsectors * fgkNstacks * fgkNlinks];
   fCurrLinkDataTypeFlags  = new UInt_t[fgkNstacks * fgkNlinks];
   fCurrLinkDebugFlags     = new UInt_t[fgkNstacks * fgkNlinks];
   fCurrLinkDataTypeFlags  = new UInt_t[fgkNstacks * fgkNlinks];
   fCurrLinkDebugFlags     = new UInt_t[fgkNstacks * fgkNlinks];
-
-  // preparing TClonesArray
-  fTrackletArray = new TClonesArray("AliTRDtrackletWord", 256);
+  for (Int_t iSector = 0; iSector < fgkNsectors; iSector++)
+    fCurrTrgFlags[iSector] = 0;
+  for (Int_t i = 0; i < 100; i++)
+    fDumpMCM[i] = 0;
 
   // setting up the error tree
   fErrors = new TTree("errorStats", "Error statistics");
   fErrors->SetDirectory(0x0);
 
   // setting up the error tree
   fErrors = new TTree("errorStats", "Error statistics");
   fErrors->SetDirectory(0x0);
-  fErrors->Branch("error", &fLastError, "sector/I:stack:link:error:rob:mcm");
+  fErrors->Branch("error", &fLastError);
   fErrors->SetCircular(1000);
   fErrors->SetCircular(1000);
+  for (Int_t i = 0; i < 100; i++) {
+    fErrorBuffer[i] = 0;
+  }
+
 }
 
 AliTRDrawStream::~AliTRDrawStream()
 }
 
 AliTRDrawStream::~AliTRDrawStream()
@@ -156,19 +273,25 @@ AliTRDrawStream::~AliTRDrawStream()
 
   delete fErrors;
 
 
   delete fErrors;
 
+  delete [] fCurrTrkHeaderIndexWord;
+  delete [] fCurrTrkHeaderSize;
+  delete [] fCurrTrkFlags;
+  delete [] fCurrTrgHeaderIndexWord;
+  delete [] fCurrTrgHeaderSize;
+  delete [] fCurrTrgFlags;
   delete [] fCurrStackIndexWord;
   delete [] fCurrStackHeaderSize;
   delete [] fCurrStackHeaderVersion;
   delete [] fCurrLinkMask;
   delete [] fCurrCleanCheckout;
   delete [] fCurrBoardId;
   delete [] fCurrStackIndexWord;
   delete [] fCurrStackHeaderSize;
   delete [] fCurrStackHeaderVersion;
   delete [] fCurrLinkMask;
   delete [] fCurrCleanCheckout;
   delete [] fCurrBoardId;
-  delete [] fCurrHwRev;
+  delete [] fCurrHwRevTMU;
   delete [] fCurrLinkMonitorFlags;
   delete [] fCurrLinkDataTypeFlags;
   delete [] fCurrLinkDebugFlags;
 }
 
   delete [] fCurrLinkMonitorFlags;
   delete [] fCurrLinkDataTypeFlags;
   delete [] fCurrLinkDebugFlags;
 }
 
-Bool_t AliTRDrawStream::ReadEvent(TTree *trackletTree)
+Bool_t AliTRDrawStream::ReadEvent()
 {
   // read the current event from the raw reader and fill it to the digits manager
 
 {
   // read the current event from the raw reader and fill it to the digits manager
 
@@ -177,14 +300,11 @@ Bool_t AliTRDrawStream::ReadEvent(TTree *trackletTree)
     return kFALSE;
   }
 
     return kFALSE;
   }
 
-  // tracklet output
-  ConnectTracklets(trackletTree);
-
   // some preparations
   fDigitsParam = 0x0;
 
   // loop over all DDLs
   // some preparations
   fDigitsParam = 0x0;
 
   // loop over all DDLs
-  // data starts with GTU payload, i.e. SMU index word
+  // data starts with GTU payload, i.e. SM index word
   UChar_t *buffer = 0x0;
 
   while (fRawReader->ReadNextData(buffer)) {
   UChar_t *buffer = 0x0;
 
   while (fRawReader->ReadNextData(buffer)) {
@@ -192,60 +312,94 @@ Bool_t AliTRDrawStream::ReadEvent(TTree *trackletTree)
     fCurrEquipmentId = fRawReader->GetEquipmentId();
     AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
 
     fCurrEquipmentId = fRawReader->GetEquipmentId();
     AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
 
-    if (fCurrEquipmentId < 1024 || fCurrEquipmentId > 1041) {
-      AliError(EquipmentError(kNonTrdEq, "Skipping"));
+    if (fCurrEquipmentId < kDDLOffset || fCurrEquipmentId > kDDLMax) {
+      EquipmentError(kNonTrdEq, "Skipping");
       continue;
     }
 
       continue;
     }
 
-    // setting the pointer to data and current reading position
-    fPayloadCurr = fPayloadStart = (UInt_t*) (buffer);
-    fPayloadSize = fRawReader->GetDataSize() / sizeof(UInt_t);
-    fStats.fStatsSector[fCurrEquipmentId - 1024].fBytes = fRawReader->GetDataSize();
-    AliDebug(2, Form("Read buffer of size: %i", fRawReader->GetDataSize()));
+    if (fMarkers)
+      new ((*fMarkers)[fMarkers->GetEntriesFast()])
+       AliTRDrawStreamError(-kSecactive, fCurrEquipmentId - kDDLOffset);
 
 
-    // read SMU index header
-    if (ReadSmHeader() < 0) {
-      AliError(Form("Reading SMU header failed, skipping this DDL %i", fCurrEquipmentId));
-      continue;
-    }
+    ReadGTUHeaders((UInt_t*) buffer);
+
+    if (fCurrTrailerReadout)
+      ReadGTUTrailer();
+
+#ifdef TRD_RAW_CRC
+    boost::crc_optimal<16, 0x8005, 0, 0, false, false>      checksumStack[5];
+    boost::crc_optimal<32, 0x04C11DB7, 0, 0, false, false>  checksumSIU;
+    checksumSIU.reset();
+
+    // process CDH, replace size with 0xffffffff
+    UInt_t temp = 0xffffffff;
+    checksumSIU.process_bytes(&temp, sizeof(UInt_t));
+    UInt_t *data = (UInt_t*) fRawReader->GetDataHeader();
+    checksumSIU.process_bytes(&data[1], 7*sizeof(UInt_t));
+    // process payload including everything but the SIU checksum
+    checksumSIU.process_bytes(buffer, fRawReader->GetDataSize()-4);
 
 
-    // read stack index header
-    for (Int_t iStack = 0; iStack < 5; iStack++) {
-      if ((fCurrStackMask & (1 << iStack)) != 0) 
-       ReadStackIndexHeader(iStack);
+    if (checksumSIU() != fCurrChecksumSIU) {
+      EquipmentError(kCRCmismatch, "SIU data - recalc: 0x%08x - 0x%08x", fCurrChecksumSIU, checksumSIU());
     }
     }
+#endif
 
 
-    for (Int_t iStack = 0; iStack < 5; iStack++) {
+    // loop over all active links
+    AliDebug(2, Form("Stack mask 0x%02x", fCurrStackMask));
+    for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
       fCurrSlot = iStack;
       fCurrSlot = iStack;
-      if ((fCurrStackMask & (1 << fCurrSlot)) == 0) 
+#ifdef TRD_RAW_CRC
+      checksumStack[iStack].reset();
+#endif
+
+      if ((fCurrStackMask & (1 << fCurrSlot)) == 0)
        continue;
 
       AliDebug(2, Form("Stack %i, Link mask: 0x%02x", fCurrSlot, fCurrLinkMask[fCurrSlot]));
        continue;
 
       AliDebug(2, Form("Stack %i, Link mask: 0x%02x", fCurrSlot, fCurrLinkMask[fCurrSlot]));
-      for (Int_t iLink = 0; iLink < 12; iLink++) {
+      for (Int_t iLink = 0; iLink < fgkNlinks; iLink++) {
        fCurrLink = iLink;
        fCurrLink = iLink;
-       fCurrHC   = fCurrSm * 60 + fCurrSlot * 12 + iLink;
+       fCurrHC   = (fCurrEquipmentId - kDDLOffset) * fgkNstacks * fgkNlinks +
+         fCurrSlot * fgkNlinks + iLink;
        if ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) == 0)
          continue;
        if ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) == 0)
          continue;
-       
-       if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0)
-         LinkError(kLinkMonitor);
-       AliDebug(2, Form("Payload for S%il%i", fCurrSlot, fCurrLink));
-       for (Int_t i = 0; i < 10; i++) //???
-         AliDebug(5, Form("%3i: 0x%08x 0x%08x 0x%08x 0x%08x", i*4,
-                fPayloadCurr[4*i], fPayloadCurr[4*i+1], 
-                fPayloadCurr[4*i+2], fPayloadCurr[4*i+3]));
 
 
-       // read the data from one HC
-       ReadLinkData();
+#ifdef TRD_RAW_CRC
+       UInt_t *start = fPayloadCurr;
+#endif
+       Int_t   size  = 0;
 
 
-       // read all data endmarkers
-       while (fPayloadCurr - fPayloadStart < fPayloadSize &&
-              *fPayloadCurr == fgkDataEndmarker)
-         fPayloadCurr++;
+       fErrorFlags = 0;
+       // check for link monitor error flag
+       if (fCurrLinkMonitorFlags[(((fCurrEquipmentId - kDDLOffset) * fgkNstacks) + fCurrSlot) * fgkNlinks + fCurrLink] != 0) {
+         LinkError(kLinkMonitor);
+         if (fgErrorBehav[kLinkMonitor] == kTolerate)
+           size += ReadLinkData();
+       }
+       else
+         // read the data from one HC
+         size += ReadLinkData();
 
 
+       // read all data endmarkers
+       size += SeekNextLink();
+
+#ifdef TRD_RAW_CRC
+       // always use data for CRC calculation
+       // (even if link monitor active)
+       UShort_t crc = CalcLinkChecksum(start, size);
+       checksumStack[iStack].process_bytes(&crc, sizeof(UShort_t));
+#endif
+      }
+#ifdef TRD_RAW_CRC
+      if (fDigitsManager && (checksumStack[iStack]() != fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][iStack])) {
+       StackError(kCRCmismatch, "data - recalc: 0x%04x - 0x%04x", fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][iStack], checksumStack[iStack]());
       }
       }
+#endif
+
+      // continue with next stack
+      SeekNextStack();
     }
   }
     }
   }
+
   return kTRUE;
 }
 
   return kTRUE;
 }
 
@@ -267,29 +421,21 @@ Bool_t AliTRDrawStream::NextDDL()
 
     fCurrEquipmentId = fRawReader->GetEquipmentId();
     AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
 
     fCurrEquipmentId = fRawReader->GetEquipmentId();
     AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
-    
-    if (fCurrEquipmentId < 1024 || fCurrEquipmentId > 1041) {
-      AliError(EquipmentError(kNonTrdEq, "Skipping"));
+
+    if (fCurrEquipmentId < kDDLOffset || fCurrEquipmentId > kDDLMax) {
+      EquipmentError(kNonTrdEq, "Skipping");
       continue;
     }
 
       continue;
     }
 
-    // setting the pointer to data and current reading position
-    fPayloadCurr = fPayloadStart = (UInt_t*) (buffer);
-    fPayloadSize = fRawReader->GetDataSize() / sizeof(UInt_t);
-    AliDebug(2, Form("Read buffer of size: %i", fRawReader->GetDataSize()));
+    if (fMarkers)
+      new ((*fMarkers)[fMarkers->GetEntriesFast()])
+       AliTRDrawStreamError(-kSecactive, fCurrEquipmentId - kDDLOffset);
+
+    ReadGTUHeaders((UInt_t*) buffer);
+
+    if (fCurrTrailerReadout)
+      ReadGTUTrailer();
 
 
-    // read SMU index header
-    if (ReadSmHeader() < 0) {
-      AliError(Form("Reading SMU header failed, skipping this DDL %i", fCurrEquipmentId));
-      continue;
-    }
-    
-    // read stack index header
-    for (Int_t iStack = 0; iStack < 5; iStack++) {
-      if ((fCurrStackMask & (1 << iStack)) != 0) {
-       ReadStackIndexHeader(iStack);
-      }
-    }
     return kTRUE;
   }
 
     return kTRUE;
   }
 
@@ -297,115 +443,702 @@ Bool_t AliTRDrawStream::NextDDL()
 }
 
 
 }
 
 
-Int_t AliTRDrawStream::NextChamber(AliTRDdigitsManager *digMgr, UInt_t ** /* trackletContainer */, UShort_t ** /* errorContainer */)
+Int_t AliTRDrawStream::NextChamber(AliTRDdigitsManager *digMgr)
 {
   // read the data for the next chamber
   // in case you only want to read the data of a single chamber
   // to read all data ReadEvent(...) is recommended
 
 {
   // read the data for the next chamber
   // in case you only want to read the data of a single chamber
   // to read all data ReadEvent(...) is recommended
 
-  fDigitsManager = digMgr; 
+  fDigitsManager = digMgr;
   fDigitsParam   = 0x0;
 
   fDigitsParam   = 0x0;
 
-  // tracklet output preparation
-  TTree *trklTree = 0x0;
-  AliRunLoader *rl = AliRunLoader::Instance();
-  AliLoader* trdLoader = rl ? rl->GetLoader("TRDLoader") : NULL;
-  AliDataLoader *trklLoader = trdLoader ? trdLoader->GetDataLoader("tracklets") : NULL;
-  if (trklLoader) {
-    AliTreeLoader *trklTreeLoader = (AliTreeLoader*) trklLoader->GetBaseLoader("tracklets-raw");
-    if (trklTreeLoader) 
-      trklTree = trklTreeLoader->Tree();
-    else 
-      trklTree = trklLoader->Tree();
-  }
-
-  if (fTrackletTree != trklTree)
-    ConnectTracklets(trklTree);
+  fErrorFlags = 0;
 
   if (!fRawReader) {
     AliError("No raw reader available");
     return -1;
   }
 
 
   if (!fRawReader) {
     AliError("No raw reader available");
     return -1;
   }
 
-  if (fCurrSlot < 0 || fCurrSlot >= 5) {
+  while (fCurrSlot < 0 || fCurrSlot >= fgkNstacks) {
     if (!NextDDL()) {
       fCurrSlot = -1;
       return -1;
     }
     if (!NextDDL()) {
       fCurrSlot = -1;
       return -1;
     }
+    while ((fCurrSlot < fgkNstacks) &&
+          (((fCurrStackMask & (1 << fCurrSlot)) == 0) ||
+           ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0)) {
+      if ((fCurrStackMask & (1 << fCurrSlot)) == 0) {
+       ++fCurrSlot;
+       fCurrSlot = 0;
+       continue;
+      }
+      fCurrLink++;
+      if (fCurrLink >= fgkNlinks) {
+       SeekNextStack();
+       fCurrLink = 0;
+       fCurrSlot++;
+      }
+    }
   }
 
   AliDebug(2, Form("Stack %i, Link %i, mask: 0x%02x", fCurrSlot, fCurrLink, fCurrLinkMask[fCurrSlot]));
   }
 
   AliDebug(2, Form("Stack %i, Link %i, mask: 0x%02x", fCurrSlot, fCurrLink, fCurrLinkMask[fCurrSlot]));
-  fCurrHC   = (fCurrEquipmentId - 1024) * 60 + fCurrSlot * 12 + fCurrLink;
+  fCurrHC   = (fCurrEquipmentId - kDDLOffset) * fgkNlinks * fgkNstacks +
+    fCurrSlot * fgkNlinks + fCurrLink;
 
 
-  if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0)
+  if (fCurrLinkMonitorFlags[(((fCurrEquipmentId - kDDLOffset) * fgkNstacks) + fCurrSlot) * fgkNlinks + fCurrLink] != 0) {
     LinkError(kLinkMonitor);
     LinkError(kLinkMonitor);
+    if (fgErrorBehav[kLinkMonitor] == kTolerate)
+      ReadLinkData();
+  }
+  else
+    // read the data from one HC
+    ReadLinkData();
 
 
-  // read the data from one HC
-  ReadLinkData();
-  
   // read all data endmarkers
   // read all data endmarkers
-  while (fPayloadCurr - fPayloadStart < fPayloadSize && 
-        *fPayloadCurr == fgkDataEndmarker) 
-    fPayloadCurr++;
+  SeekNextLink();
 
   if (fCurrLink % 2 == 0) {
     // if we just read the A-side HC then also check the B-side
     fCurrLink++;
     fCurrHC++;
     if (fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) {
 
   if (fCurrLink % 2 == 0) {
     // if we just read the A-side HC then also check the B-side
     fCurrLink++;
     fCurrHC++;
     if (fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) {
-      ReadLinkData();
-      while (fPayloadCurr - fPayloadStart < fPayloadSize && 
-            *fPayloadCurr == fgkDataEndmarker) 
-       fPayloadCurr++;
+      if (fCurrLinkMonitorFlags[(((fCurrEquipmentId - kDDLOffset) * fgkNstacks) + fCurrSlot) * fgkNlinks + fCurrLink] != 0) {
+       LinkError(kLinkMonitor);
+       if (fgErrorBehav[kLinkMonitor] == kTolerate)
+         ReadLinkData();
+      }
+      else {
+       ReadLinkData();
+      }
+      SeekNextLink();
     }
   }
 
     }
   }
 
-  //??? to check 
   do {
   do {
-    fCurrLink++; 
-    if (fCurrLink > 11) {
+    if ((fCurrStackMask & (1 << fCurrSlot)) == 0) {
       fCurrLink = 0;
       fCurrSlot++;
     }
       fCurrLink = 0;
       fCurrSlot++;
     }
-  } while ((fCurrSlot < 5) && 
-          (((fCurrStackMask & (1 << fCurrSlot)) == 0) || 
+    else {
+      fCurrLink++;
+      if (fCurrLink >= fgkNlinks) {
+       SeekNextStack();
+       fCurrLink = 0;
+       fCurrSlot++;
+      }
+    }
+  } while ((fCurrSlot < fgkNstacks) &&
+          (((fCurrStackMask & (1 << fCurrSlot)) == 0) ||
            ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0));
 
            ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0));
 
-  return (fCurrSm * 30 + fCurrStack * 6 + fCurrLayer);
+  // return chamber information from HC if it is valid
+  // otherwise return information from link position
+  if (fCurrSm < 0 || fCurrSm >= fgkNsectors || fCurrStack < 0 || fCurrStack >= fgkNstacks || fCurrLayer < 0 || fCurrLayer >= fgkNlinks/2)
+    return ((fCurrEquipmentId-kDDLOffset) + fCurrSlot * fgkNlinks/2 + fCurrLink/2);
+  else
+    return (fCurrSm * fgkNstacks*fgkNlinks/2 + fCurrStack * fgkNlinks/2 + fCurrLayer);
 }
 
 
 }
 
 
+Int_t AliTRDrawStream::ReadGTUHeaders(UInt_t *buffer)
+{
+  // check the data source and read the headers
+
+  if (fCurrEquipmentId >= kDDLOffset && fCurrEquipmentId <= kDDLMax) {
+    // this is ROC data
+
+    // setting the pointer to data and current reading position
+    fPayloadCurr = fPayloadStart = buffer;
+    fPayloadSize = fRawReader->GetDataSize() / sizeof(UInt_t);
+    fStats.fStatsSector[fCurrEquipmentId - kDDLOffset].fBytes = fRawReader->GetDataSize();
+    AliDebug(2, Form("Read buffer of size: %i", fRawReader->GetDataSize()));
+
+    AliDebug(1, DumpRaw("raw data", fPayloadCurr, TMath::Min(fPayloadSize, 1000)));
+
+    // read SM header
+    if (ReadSmHeader() < 0) {
+      AliError(Form("Reading SM header failed, skipping this DDL %i", fCurrEquipmentId));
+      return -1;
+    }
+
+    // read tracking headers (if available)
+    if (fCurrTrkHeaderAvail) {
+      for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
+       if ((fCurrStackMask & (1 << iStack)) != 0)
+         ReadTrackingHeader(iStack);
+      }
+    }
+
+    // read trigger header(s) (if available)
+    if (fCurrTrgHeaderAvail)
+      ReadTriggerHeaders();
+
+    // read stack header
+    for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
+      if ((fCurrStackMask & (1 << iStack)) != 0)
+       ReadStackHeader(iStack);
+    }
+
+    return 0;
+  }
+  else
+    return -1;
+}
+
 Int_t AliTRDrawStream::ReadSmHeader()
 {
 Int_t AliTRDrawStream::ReadSmHeader()
 {
-  // read the SMU index header at the current reading position 
+  // read the SMU index header at the current reading position
   // and store the information in the corresponding variables
 
   if (fPayloadCurr - fPayloadStart >= fPayloadSize - 1) {
   // and store the information in the corresponding variables
 
   if (fPayloadCurr - fPayloadStart >= fPayloadSize - 1) {
-    AliError(EquipmentError(kUnknown, "SM Header incomplete"));
+    EquipmentError(kUnknown, "SM Header incomplete");
     return -1;
   }
 
     return -1;
   }
 
-  fCurrSmuIndexHeaderSize     = ((*fPayloadCurr) >> 16) & 0xffff;
-  fCurrSmuIndexHeaderVersion  = ((*fPayloadCurr) >> 12) &    0xf;
+  fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] = 0;
+
+  fCurrSmHeaderSize           = ((*fPayloadCurr) >> 16) & 0xffff;
+  fCurrSmHeaderVersion        = ((*fPayloadCurr) >> 12) &    0xf;
   fCurrTrackEnable            = ((*fPayloadCurr) >>  6) &    0x1;
   fCurrTrackletEnable         = ((*fPayloadCurr) >>  5) &    0x1;
   fCurrStackMask              = ((*fPayloadCurr)      ) &   0x1f;
   fCurrTrackEnable            = ((*fPayloadCurr) >>  6) &    0x1;
   fCurrTrackletEnable         = ((*fPayloadCurr) >>  5) &    0x1;
   fCurrStackMask              = ((*fPayloadCurr)      ) &   0x1f;
+  fCurrHwRev                  = (fPayloadCurr[1] >> 12) & 0xffff;
+  fCurrStackEndmarkerAvail    = 0;
+
+  switch (fCurrSmHeaderVersion) {
+  case 0xb:
+    fCurrTrailerReadout = 0;
+    fCurrTrgHeaderAvail = 0;
+    fCurrEvType = 0;
+    fCurrTrkHeaderAvail = 0;
+
+    DecodeGTUtracks();
+    break;
+
+  case 0xc:
+    fCurrTrailerReadout = ((*fPayloadCurr) >> 10) &    0x1;
+    fCurrTrgHeaderAvail = 1;
+    fCurrTrgHeaderReadout = ((*fPayloadCurr) >>  9) &    0x1;
+    fCurrEvType         = ((*fPayloadCurr) >>  7) &    0x3;
+    fCurrTrkHeaderAvail = fCurrTrackEnable;
+    fCurrTriggerEnable  = (fPayloadCurr[2] >>  8) &  0xfff;
+    fCurrTriggerFired   = (fPayloadCurr[2] >>  20) &  0xfff;
+    fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] = fCurrTriggerFired;
+    break;
+
+  case 0xd:
+    fCurrTrailerReadout = ((*fPayloadCurr) >> 10) &    0x1;
+    fCurrTrgHeaderAvail = 1;
+    fCurrTrgHeaderReadout = ((*fPayloadCurr) >>  9) &    0x1;
+    fCurrEvType         = ((*fPayloadCurr) >>  7) &    0x3;
+    fCurrTrkHeaderAvail = fCurrTrackEnable;
+    fCurrTriggerEnable  = (fPayloadCurr[2] >>  8) &  0xfff;
+    fCurrTriggerFired   = (fPayloadCurr[2] >>  20) &  0xfff;
+    fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] = fCurrTriggerFired;
+    fCurrStackEndmarkerAvail    = 1;
+#ifdef TRD_RAW_DEBUG
+    if (fCurrSmHeaderSize > 7) {
+      fCurrL0Count[fCurrEquipmentId-kDDLOffset]  = fPayloadCurr[3];
+      fCurrL1aCount[fCurrEquipmentId-kDDLOffset] = fPayloadCurr[4];
+      fCurrL1rCount[fCurrEquipmentId-kDDLOffset] = fPayloadCurr[5];
+      fCurrL2aCount[fCurrEquipmentId-kDDLOffset] = fPayloadCurr[6];
+      fCurrL2rCount[fCurrEquipmentId-kDDLOffset] = fPayloadCurr[7];
+    }
+#endif
+    break;
 
 
-  AliDebug(5, Form("SMU header: size: %i, version: %i, track enable: %i, tracklet enable: %i, stack mask: %2x",
-                  fCurrSmuIndexHeaderSize, 
-                  fCurrSmuIndexHeaderVersion, 
-                  fCurrTrackEnable, 
+  default:
+    AliError(Form("unknown SM header version: 0x%x", fCurrSmHeaderVersion));
+  }
+
+  AliDebug(5, Form("SM header: size: %i, version: %i, track enable: %i, tracklet enable: %i, stack mask: %2x, trailer: %i, trgheader: %i, trkheader: %i",
+                  fCurrSmHeaderSize,
+                  fCurrSmHeaderVersion,
+                  fCurrTrackEnable,
                   fCurrTrackletEnable,
                   fCurrTrackletEnable,
-                  fCurrStackMask));
-  
-  fPayloadCurr += fCurrSmuIndexHeaderSize + 1;
+                  fCurrStackMask,
+                  fCurrTrailerReadout,
+                  fCurrTrgHeaderAvail,
+                  fCurrTrkHeaderAvail ));
+
+  // jump to the first word after the SM header
+  fPayloadCurr += fCurrSmHeaderSize + 1;
 
 
-  return fCurrSmuIndexHeaderSize + 1;
+  return fCurrSmHeaderSize + 1;
 }
 
 }
 
-Int_t AliTRDrawStream::ReadStackIndexHeader(Int_t stack)
+Int_t AliTRDrawStream::DecodeGTUtracks()
 {
 {
-  // read the stack index header 
+  // decode GTU track words
+  // this depends on the hardware revision of the SMU
+
+  Int_t sector = fCurrEquipmentId-kDDLOffset;
+
+  if ((sector < 0) || (sector > 17)) {
+    AliError(Form("Invalid sector %i for GTU tracks", sector));
+    return -1;
+  }
+
+  AliDebug(1, DumpRaw(Form("GTU tracks in sector %2i (hw rev %i)", sector, fCurrHwRev),
+                     fPayloadCurr + 4, 10, 0xffe0ffff));
+
+  fCurrTrgFlags[sector] = 0;
+
+  if (fCurrHwRev < 1772) {
+    UInt_t    fastWord;                // fast trigger word
+    ULong64_t trackWord = 0;   // extended track word
+    Int_t stack = 0;
+    Int_t idx = 0;
+    for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
+      if (fPayloadCurr[iWord] == 0x10000000) { // stack boundary marker
+        stack++;
+        idx = 0;
+      }
+      else {
+        if ((idx == 0) &&
+           ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
+         fastWord = fPayloadCurr[iWord];
+         fCurrTrgFlags[sector] |= 1 << (stack+11); // assume tracking done if fast word sent
+         AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
+         continue;
+        }
+        else if ((idx & 0x1) == 0x1) {
+         trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
+         AliDebug(1,Form("track debug word: 0x%016llx", trackWord));
+         if (fTracks) {
+           AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
+             AliESDTrdTrack();
+
+           trk->SetSector(sector);
+           trk->SetStack((trackWord >> 60) & 0x7);
+           trk->SetA(0);
+           trk->SetB(0);
+           trk->SetPID(0);
+           trk->SetLayerMask((trackWord >> 16) & 0x3f);
+           trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
+           trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
+           trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
+           trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
+           trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
+           trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
+
+           trk->SetFlags(0);
+           trk->SetReserved(0);
+           trk->SetLabel(-3);
+
+           Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
+           if (TMath::Abs(pt) > 0.1) {
+             trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
+           }
+         }
+       }
+        else {
+         trackWord = fPayloadCurr[iWord];
+        }
+        idx++;
+      }
+    }
+  }
+  else if (fCurrHwRev < 1804) {
+    UInt_t    fastWord;                // fast trigger word
+    ULong64_t trackWord = 0;   // extended track word
+    Int_t stack = 0;
+    Int_t idx = 0;
+    for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
+      if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
+        stack++;
+        idx = 0;
+      }
+      else {
+        if ((idx == 0) &&
+           ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
+         fastWord = fPayloadCurr[iWord];
+         fCurrTrgFlags[sector] |= 1 << (stack+11); // assume tracking done if fast word sent
+         AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
+         continue;
+        }
+        else if ((idx & 0x1) == 0x1) {
+         trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
+         AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
+         if (fTracks) {
+           AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
+             AliESDTrdTrack();
+
+           trk->SetSector(fCurrEquipmentId-kDDLOffset);
+           trk->SetStack((trackWord >> 60) & 0x7);
+           trk->SetA(0);
+           trk->SetB(0);
+           trk->SetPID(0);
+           trk->SetLayerMask((trackWord >> 16) & 0x3f);
+           trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
+           trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
+           trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
+           trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
+           trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
+           trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
+
+           trk->SetFlags(0);
+           trk->SetReserved(0);
+           trk->SetLabel(-3);
+
+           Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
+           if (TMath::Abs(pt) > 0.1) {
+             trk->SetA((Int_t) (-0.15*51625./100./pt / 160e-4 * 2));
+           }
+         }
+        }
+        else {
+         trackWord = fPayloadCurr[iWord];
+        }
+        idx++;
+      }
+    }
+  }
+  else if (fCurrHwRev < 1819) {
+    UInt_t    fastWord;                // fast trigger word
+    ULong64_t trackWord = 0;   // extended track word
+    Int_t stack = 0;
+    Int_t idx = 0;
+    for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
+      if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
+       stack++;
+       idx = 0;
+      }
+      else {
+       if ((idx == 0) &&
+           ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
+         fastWord = fPayloadCurr[iWord];
+         if (fastWord & (1 << 13))
+           fCurrTrgFlags[sector] |= 1 << (stack+11);
+         AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
+         continue;
+       }
+       else if ((idx & 0x1) == 0x1) {
+         trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
+         AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
+
+         if (fTracks) {
+           AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
+             AliESDTrdTrack();
+
+           trk->SetSector(fCurrEquipmentId-kDDLOffset);
+           trk->SetStack((trackWord >> 60) & 0x7);
+           trk->SetA(0);
+           trk->SetB(0);
+           // trk->SetPt(((trackWord & 0xffff) ^ 0x8000) - 0x8000);
+           trk->SetPID(0);
+           trk->SetLayerMask((trackWord >> 16) & 0x3f);
+           trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
+           trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
+           trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
+           trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
+           trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
+           trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
+
+           trk->SetFlags(0);
+           trk->SetReserved(0);
+           trk->SetLabel(-3);
+
+           Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
+           if (TMath::Abs(pt) > 0.1) {
+             trk->SetA((Int_t) (0.15*51625./100./trk->Pt() / 160e-4 * 2));
+           }
+         }
+       }
+       else {
+         trackWord = fPayloadCurr[iWord];
+       }
+       idx++;
+      }
+    }
+  }
+  else if (fCurrHwRev < 1860) {
+    UInt_t    fastWord;                // fast trigger word
+    ULong64_t trackWord = 0;   // extended track word
+    Int_t stack = 0;
+    Int_t idx = 0;
+    Bool_t upperWord = kFALSE;
+    Int_t word = 0;
+    for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
+      if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
+        stack++;
+        idx = 0;
+       upperWord = kFALSE;
+      }
+      else {
+       // assemble the 32-bit words out of 16-bit blocks
+       if (upperWord) {
+         word |= (fPayloadCurr[iWord] & 0xffff0000);
+         upperWord = kFALSE;
+       }
+       else {
+         // lower word is read first
+         word = (fPayloadCurr[iWord] & 0xffff0000) >> 16;
+         upperWord = kTRUE;
+         continue;
+       }
+
+        if ((word & 0xffff0008) == 0x13370008) {
+         fastWord = word;
+         AliDebug(1, Form("stack %i: fast track word: 0x%08x", stack, fastWord));
+         if (fastWord & (1 << 13))
+           fCurrTrgFlags[sector] |= 1 << (stack+11);
+         continue;
+        }
+        else if ((idx & 0x1) == 0x1) {
+         trackWord |= ((ULong64_t) word) << 32;
+         AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
+         if (fTracks) {
+           AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
+             AliESDTrdTrack();
+
+           trk->SetSector(fCurrEquipmentId-kDDLOffset);
+           trk->SetStack((trackWord >> 60) & 0x7);
+           trk->SetA(0);
+           trk->SetB(0);
+           trk->SetPID(0);
+           trk->SetLayerMask((trackWord >> 16) & 0x3f);
+           trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
+           trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
+           trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
+           trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
+           trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
+           trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
+
+           trk->SetFlags(0);
+           trk->SetReserved(0);
+           trk->SetLabel(-3);
+
+           Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
+           if (TMath::Abs(pt) > 0.1) {
+             trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
+           }
+         }
+        }
+        else {
+         trackWord = word;
+        }
+        idx++;
+      }
+    }
+
+  }
+  else {
+    ULong64_t trackWord = 0; // this is the debug word
+    Int_t stack = 0;
+    Int_t idx = 0;
+    Bool_t upperWord = kFALSE;
+    Int_t word = 0;
+    for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
+      if (fPayloadCurr[iWord] == 0xffe0ffff) {
+        stack++;
+        idx = 0;
+       upperWord = kFALSE;
+      }
+      else {
+       // assemble the 32-bit words out of 16-bit blocks
+       if (upperWord) {
+         word |= (fPayloadCurr[iWord] & 0xffff0000);
+         upperWord = kFALSE;
+       }
+       else {
+         // lower word is read first
+         word = (fPayloadCurr[iWord] & 0xffff0000) >> 16;
+         upperWord = kTRUE;
+         continue;
+       }
+
+        if ((word & 0xffff0008) == 0x13370008) {
+         AliDebug(1, Form("stack %i: fast track word: 0x%08x", stack, word));
+         continue;
+        }
+        else if ((word & 0xffff0010) == 0x13370010) {
+         AliDebug(1, Form("stack %i: tracking done word: 0x%08x", stack, word));
+         fCurrTrgFlags[sector] |= 1 << (stack+11);
+         continue;
+       }
+        else if ((idx & 0x1) == 0x1) {
+         trackWord |= ((ULong64_t) word) << 32;
+         AliDebug(1, Form("track debug word: 0x%16llx", trackWord));
+         if (fTracks) {
+           AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
+             AliESDTrdTrack();
+           trk->SetSector(fCurrEquipmentId-kDDLOffset);
+           trk->SetStack((trackWord >> 60) & 0x7);
+           trk->SetA(0);
+           trk->SetB(0);
+           trk->SetPID(0);
+           trk->SetLayerMask((trackWord >> 16) & 0x3f);
+           trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
+           trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
+           trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
+           trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
+           trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
+           trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
+
+           trk->SetFlags(0);
+           trk->SetReserved(0);
+           trk->SetLabel(-3);
+
+           Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
+           if (TMath::Abs(pt) > 0.1) {
+             trk->SetA(-(Int_t) (0.15*51625./100./pt / 160e-4 * 2));
+           }
+         }
+        }
+        else {
+         trackWord = word;
+        }
+        idx++;
+      }
+    }
+  }
+  return 0;
+}
+
+Int_t AliTRDrawStream::ReadTrackingHeader(Int_t stack)
+{
+  // read the tracking information and store it for the given stack
+
+  // index word
+
+  fCurrTrkHeaderIndexWord[stack] = *fPayloadCurr;
+  fCurrTrkHeaderSize[stack]      = ((*fPayloadCurr) >> 16) & 0x3ff;
+
+  AliDebug(1, Form("tracking header index word: 0x%08x, size: %i (hw rev: %i)",
+                  fCurrTrkHeaderIndexWord[stack], fCurrTrkHeaderSize[stack], fCurrHwRev));
+  Int_t trackingTime = *fPayloadCurr & 0x3ff;
+
+  fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] |= ((fCurrTrkHeaderIndexWord[stack] >> 10) & 0x1) << (22 + stack);
+  fPayloadCurr++;
+
+  // data words
+  ULong64_t trackWord = 0;
+  Int_t idx = 0;
+  Int_t trackIndex = fTracks ? fTracks->GetEntriesFast() : -1;
+
+  for (UInt_t iWord = 0; iWord < fCurrTrkHeaderSize[stack]; iWord++) {
+
+    if (!(idx & 0x1)) {
+      // first part of 64-bit word
+      trackWord = fPayloadCurr[iWord];
+    }
+    else {
+      trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
+
+      if (trackWord & (1ul << 63)) {
+       if ((trackWord & (0x3ful << 56)) != 0) {
+         // track word
+         AliDebug(2, Form("track word: 0x%016llx", trackWord));
+
+         if (fTracks) {
+           AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
+             AliESDTrdTrack();
+
+           trk->SetSector(fCurrEquipmentId-kDDLOffset);
+           trk->SetLayerMask((trackWord >> 56) & 0x3f);
+           trk->SetA( (((trackWord >> 38) & 0x3ffff) ^ 0x20000) - 0x20000);
+           trk->SetB( (((trackWord >> 20) & 0x3ffff) ^ 0x20000) - 0x20000);
+           trk->SetC( (((trackWord >> 8)  &  0xffff) ^  0x8000) -  0x8000);
+           trk->SetPID((trackWord >>  0) & 0xff);
+           trk->SetStack(stack);
+           trk->SetLabel(-3);
+
+           // now compare the track word with the one generated from the ESD information
+           if (trackWord != trk->GetTrackWord(0)) {
+             AliError(Form("track word 0x%016llx does not match the read one 0x%016llx",
+                           trk->GetTrackWord(0), trackWord));
+           }
+         }
+       }
+       else {
+         // done marker (so far only used to set trigger flag)
+         fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] |= 1 << (27 + stack);
+         fCurrTrkFlags[(fCurrEquipmentId-kDDLOffset)*fgkNstacks + stack] = trackWord;
+
+         AliDebug(2, Form("tracking done marker: 0x%016llx, trigger flags: 0x%08x",
+                          trackWord, fCurrTrgFlags[fCurrEquipmentId-kDDLOffset]));
+         AliDebug(2, Form("seg / stack / first / last / done / index : %i %i %lli %lli %lli %i",
+                          fCurrEquipmentId - kDDLOffset, stack,
+                          (trackWord >> 20) & 0x3ff,
+                          (trackWord >> 10) & 0x3ff,
+                          (trackWord >>  0) & 0x3ff,
+                          trackingTime));
+       }
+      }
+      else {
+       // extended track word
+       AliDebug(2, Form("extended track word: 0x%016llx", trackWord));
+
+       if (fTracks) {
+         AliESDTrdTrack *trk = (AliESDTrdTrack*) (*fTracks)[trackIndex];
+
+         trk->SetFlags((trackWord >> 52) & 0x7ff);
+         trk->SetFlagsTiming((trackWord >> 51) & 0x1);
+         trk->SetReserved((trackWord >> 49) & 0x3);
+         trk->SetY((trackWord >> 36) & 0x1fff);
+         trk->SetTrackletIndex((trackWord >>  0) & 0x3f, 0);
+         trk->SetTrackletIndex((trackWord >>  6) & 0x3f, 1);
+         trk->SetTrackletIndex((trackWord >> 12) & 0x3f, 2);
+         trk->SetTrackletIndex((trackWord >> 18) & 0x3f, 3);
+         trk->SetTrackletIndex((trackWord >> 24) & 0x3f, 4);
+         trk->SetTrackletIndex((trackWord >> 30) & 0x3f, 5);
+
+         if (trk->GetFlagsTiming() == 0) {
+           AliError(Form("*** track not in time: 0x%016llx", trk->GetExtendedTrackWord(0)));
+         }
+
+         if (trackWord != trk->GetExtendedTrackWord(0)) {
+           AliError(Form("extended track word 0x%016llx does not match the read one 0x%016llx",
+                         trk->GetExtendedTrackWord(0), trackWord));
+           }
+
+         trackIndex++;
+       }
+      }
+    }
+    idx++;
+  }
+
+  fPayloadCurr += fCurrTrkHeaderSize[stack];
+
+  return fCurrTrkHeaderSize[stack];
+}
+
+Int_t AliTRDrawStream::ReadTriggerHeaders()
+{
+  // read all trigger headers present
+
+  AliDebug(1, Form("trigger mask: 0x%03x, fired: 0x%03x\n",
+                  fCurrTriggerEnable, fCurrTriggerFired));
+  // loop over potential trigger blocks
+  for (Int_t iTrigger = 0; iTrigger < fgkNtriggers; iTrigger++) {
+    // check for trigger enable
+    if (fCurrTriggerEnable & (1 << iTrigger)) {
+      // check for readout mode and trigger fired
+      if ((fCurrTrgHeaderReadout == 0) || (fCurrTriggerFired & (1 << iTrigger))) {
+       // index word
+       AliDebug(1, Form("trigger index word %i: 0x%08x\n", iTrigger, *fPayloadCurr));
+       fCurrTrgHeaderIndexWord[iTrigger] = *fPayloadCurr;
+       fCurrTrgHeaderSize[iTrigger]      = ((*fPayloadCurr) >> 16) & 0x3ff;
+       if (iTrigger == 7) {
+         // timeout trigger, use to extract tracking time
+         fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] |= (*fPayloadCurr & 0x3ff) << 12;
+       }
+
+       fPayloadCurr++;
+       // data words
+       fPayloadCurr += fCurrTrgHeaderSize[iTrigger];
+      }
+    }
+  }
+
+  return 0;
+}
+
+Int_t AliTRDrawStream::ReadStackHeader(Int_t stack)
+{
+  // read the stack header
   // and store the information in the corresponding variables
 
   fCurrStackIndexWord[stack]     = *fPayloadCurr;
   // and store the information in the corresponding variables
 
   fCurrStackIndexWord[stack]     = *fPayloadCurr;
@@ -413,44 +1146,100 @@ Int_t AliTRDrawStream::ReadStackIndexHeader(Int_t stack)
   fCurrStackHeaderVersion[stack] = ((*fPayloadCurr) >> 12) & 0xf;
   fCurrLinkMask[stack]           = (*fPayloadCurr) & 0xfff;
 
   fCurrStackHeaderVersion[stack] = ((*fPayloadCurr) >> 12) & 0xf;
   fCurrLinkMask[stack]           = (*fPayloadCurr) & 0xfff;
 
+  // dumping stack header
+  AliDebug(1, DumpRaw(Form("stack %i header", stack), fPayloadCurr, fCurrStackHeaderSize[stack]));
+
   if (fPayloadCurr - fPayloadStart >= fPayloadSize - (Int_t) fCurrStackHeaderSize[stack]) {
   if (fPayloadCurr - fPayloadStart >= fPayloadSize - (Int_t) fCurrStackHeaderSize[stack]) {
-    AliError(StackError(kStackHeaderInvalid, "Stack index header aborted"));
+    EquipmentError(kStackHeaderInvalid, "Stack index header %i incomplete", stack);
+    // dumping stack header
+    AliError(DumpRaw(Form("stack %i header", stack), fPayloadCurr, fCurrStackHeaderSize[stack]));
+
     return -1;
   }
 
   switch (fCurrStackHeaderVersion[stack]) {
     return -1;
   }
 
   switch (fCurrStackHeaderVersion[stack]) {
-  case 0xa: 
+  case 0xa:
+  case 0xb:
     if (fCurrStackHeaderSize[stack] < 8) {
     if (fCurrStackHeaderSize[stack] < 8) {
-      AliError(StackError(kStackHeaderInvalid, "Stack header smaller than expected!"));
+      LinkError(kStackHeaderInvalid, "Stack header smaller than expected!");
       return -1;
     }
       return -1;
     }
-    
+
     fCurrCleanCheckout[stack] = fPayloadCurr[1] & 0x1;
     fCurrBoardId[stack]       = (fPayloadCurr[1] >> 8) & 0xff;
     fCurrCleanCheckout[stack] = fPayloadCurr[1] & 0x1;
     fCurrBoardId[stack]       = (fPayloadCurr[1] >> 8) & 0xff;
-    fCurrHwRev[stack]         = (fPayloadCurr[1] >> 16) & 0xffff;
-    
+    fCurrHwRevTMU[stack]      = (fPayloadCurr[1] >> 16) & 0xffff;
+
     for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
       // A side
     for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
       // A side
-      fCurrLinkMonitorFlags  [stack*fgkNlinks + iLayer*2]      = fPayloadCurr[iLayer+2] & 0xf;
-      fCurrLinkDataTypeFlags [stack*fgkNlinks + iLayer*2]      = (fPayloadCurr[iLayer+2] >> 4) & 0x3;
-      fCurrLinkDebugFlags    [stack*fgkNlinks + iLayer*2]      = (fPayloadCurr[iLayer+2] >> 12) & 0xf;
+      fCurrLinkMonitorFlags  [((fCurrEquipmentId - kDDLOffset) * fgkNstacks + stack) *fgkNlinks + iLayer*2] = fPayloadCurr[iLayer+2] & 0xf;
+      fCurrLinkDataTypeFlags [stack * fgkNlinks + iLayer*2]      = (fPayloadCurr[iLayer+2] >> 4) & 0x3;
+      fCurrLinkDebugFlags    [stack * fgkNlinks + iLayer*2]      = (fPayloadCurr[iLayer+2] >> 12) & 0xf;
       // B side
       // B side
-      fCurrLinkMonitorFlags  [stack*fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 16) & 0xf;
-      fCurrLinkDataTypeFlags [stack*fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 20) & 0x3;
-      fCurrLinkDebugFlags    [stack*fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 28) & 0xf;
+      fCurrLinkMonitorFlags  [((fCurrEquipmentId - kDDLOffset) * fgkNstacks + stack) *fgkNlinks + iLayer*2 + 1] = (fPayloadCurr[iLayer+2] >> 16) & 0xf;
+      fCurrLinkDataTypeFlags [stack * fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 20) & 0x3;
+      fCurrLinkDebugFlags    [stack * fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 28) & 0xf;
     }
     break;
     }
     break;
-    
+
   default:
   default:
-    AliError(StackError(kStackHeaderInvalid, Form("Invalid Stack Index Header version %x", 
-                                                 fCurrStackHeaderVersion[stack])));
+    EquipmentError(kStackHeaderInvalid, "Invalid Stack Header version %x", fCurrStackHeaderVersion[stack]);
   }
   }
-  
+
   fPayloadCurr += fCurrStackHeaderSize[stack];
 
   return fCurrStackHeaderSize[stack];
 }
 
   fPayloadCurr += fCurrStackHeaderSize[stack];
 
   return fCurrStackHeaderSize[stack];
 }
 
+Int_t AliTRDrawStream::ReadGTUTrailer()
+{
+  // read the SM trailer containing CRCs from various stages
+
+  UInt_t* trailer = fPayloadStart + fPayloadSize -1;
+
+  // look for the trailer index word from the end
+  for (Int_t iWord = 0; iWord < fPayloadSize-2; iWord++) {
+    if ((fPayloadStart[fPayloadSize-3-iWord] == fgkStackEndmarker[0]) &&
+       (fPayloadStart[fPayloadSize-2-iWord] == fgkStackEndmarker[1]) &&
+       ((fPayloadStart[fPayloadSize-1-iWord] & 0xfff) == 0xf51)) {
+      trailer = fPayloadStart + fPayloadSize - 1 - iWord;
+      break;
+    }
+  }
+
+  if (((*trailer) & 0xfff) == 0xf51) {
+    UInt_t trailerIndexWord = (*trailer);
+    Int_t trailerSize = (trailerIndexWord >> 16) & 0xffff;
+    // Int_t trailerVersion = (trailerIndexWord >> 12) & 0xf;
+    AliDebug(2, DumpRaw("GTU trailer", trailer, trailerSize+1));
+    // parse the trailer
+    if (trailerSize >= 4) {
+      // match flags from GTU
+      fCurrMatchFlagsSRAM[fCurrEquipmentId-kDDLOffset]     = (trailer[1] >>  0) &    0x1f;
+      fCurrMatchFlagsPostBP[fCurrEquipmentId-kDDLOffset]   = (trailer[1] >>  5) &    0x1f;
+      // individual checksums
+      fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][0]   = (trailer[1] >> 16) &  0xffff;
+      fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][1]   = (trailer[2] >>  0) &  0xffff;
+      fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][2]   = (trailer[2] >> 16) &  0xffff;
+      fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][3]   = (trailer[3] >>  0) &  0xffff;
+      fCurrChecksumStack[fCurrEquipmentId - kDDLOffset][4]   = (trailer[3] >> 16) &  0xffff;
+      fCurrChecksumSIU        = trailer[trailerSize];
+
+      if ((fCurrMatchFlagsSRAM[fCurrEquipmentId-kDDLOffset] & fCurrStackMask) != fCurrStackMask)
+       EquipmentError(kCRCmismatch, "CRC mismatch SRAM: 0x%02x", fCurrMatchFlagsSRAM[fCurrEquipmentId-kDDLOffset]);
+      if ((fCurrMatchFlagsPostBP[fCurrEquipmentId-kDDLOffset] & fCurrStackMask) != fCurrStackMask)
+       EquipmentError(kCRCmismatch, "CRC mismatch BP: 0x%02x", fCurrMatchFlagsPostBP[fCurrEquipmentId-kDDLOffset]);
+
+    }
+    else {
+      LinkError(kUnknown, "Invalid GTU trailer");
+    }
+  }
+  else
+    EquipmentError(kUnknown, "trailer index marker mismatch");
+
+  return 0;
+}
+
 Int_t AliTRDrawStream::ReadLinkData()
 {
   // read the data in one link (one HC) until the data endmarker is reached
 Int_t AliTRDrawStream::ReadLinkData()
 {
   // read the data in one link (one HC) until the data endmarker is reached
@@ -459,53 +1248,31 @@ Int_t AliTRDrawStream::ReadLinkData()
   Int_t count = 0;
   UInt_t* startPosLink = fPayloadCurr;
 
   Int_t count = 0;
   UInt_t* startPosLink = fPayloadCurr;
 
-//  printf("----- HC: %i -----\n", fCurrHC);
-//  for (Int_t i = 0; i < 3; i++) {
-//    printf("0x%08x 0x%08x 0x%08x 0x%08x\n", 
-//        fPayloadCurr[i*4+0], fPayloadCurr[i*4+1], fPayloadCurr[i*4+2], fPayloadCurr[i*4+3]);
-//  }
+  AliDebug(1, DumpRaw(Form("link data from seg %2i slot %i link %2i", fCurrEquipmentId-kDDLOffset, fCurrSlot, fCurrLink),
+                     fPayloadCurr, TMath::Min((Int_t) (fPayloadSize - (fPayloadCurr-fPayloadStart)), 100), 0x00000000));
+
+  if (fMarkers)
+    new ((*fMarkers)[fMarkers->GetEntriesFast()])
+      AliTRDrawStreamError(-kHCactive, fCurrEquipmentId-kDDLOffset, fCurrSlot, fCurrLink);
 
 
-  count += ReadTracklets();
+  if (fErrorFlags & kDiscardHC)
+    return count;
 
 
+  if (fCurrTrackletEnable) {
+    count += ReadTracklets();
+    if (fErrorFlags & kDiscardHC)
+      return count;
+  }
+
+  AliDebug(1, DumpRaw("HC header", fPayloadCurr, 4, 0x00000000));
   count += ReadHcHeader();
   count += ReadHcHeader();
+  if (fErrorFlags & kDiscardHC)
+    return count;
 
   Int_t det = fCurrSm * 30 + fCurrStack * 6 + fCurrLayer;
 
   if (det > -1 && det < 540) {
 
   Int_t det = fCurrSm * 30 + fCurrStack * 6 + fCurrLayer;
 
   if (det > -1 && det < 540) {
-    
-    if ((fAdcArray = fDigitsManager->GetDigits(det))) {
-      //fAdcArray->Expand();
-      if (fAdcArray->GetNtime() != fCurrNtimebins)
-       fAdcArray->Allocate(16, 144, fCurrNtimebins);
-    }
-    else {
-      AliError(LinkError(kNoDigits));
-    }
-    
-    if (!fDigitsParam) {
-      fDigitsParam = fDigitsManager->GetDigitsParam();
-    }
-    if (fDigitsParam) {
-      fDigitsParam->SetPretriggerPhase(det, fCurrPtrgPhase);
-      fDigitsParam->SetNTimeBins(det, fCurrNtimebins);
-      fDigitsParam->SetADCbaseline(det, 10);
-    }
-    
-    if (fDigitsManager->UsesDictionaries()) {
-      fDigitsManager->GetDictionary(det, 0)->Reset();
-      fDigitsManager->GetDictionary(det, 1)->Reset();
-      fDigitsManager->GetDictionary(det, 2)->Reset();
-    }
 
 
-    if ((fSignalIndex = fDigitsManager->GetIndexes(det))) {
-      fSignalIndex->SetSM(fCurrSm);
-      fSignalIndex->SetStack(fCurrStack);
-      fSignalIndex->SetLayer(fCurrLayer);
-      fSignalIndex->SetDetNumber(det);
-      if (!fSignalIndex->IsAllocated())
-       fSignalIndex->Allocate(16, 144, fCurrNtimebins);
-    }
-    
     // ----- check which kind of data -----
     if (fCurrMajor & 0x40) {
       if ((fCurrMajor & 0x7) == 0x7) {
     // ----- check which kind of data -----
     if (fCurrMajor & 0x40) {
       if ((fCurrMajor & 0x7) == 0x7) {
@@ -515,37 +1282,86 @@ Int_t AliTRDrawStream::ReadLinkData()
               *fPayloadCurr != fgkDataEndmarker)
          fPayloadCurr++;
        count += fPayloadCurr - startPos;
               *fPayloadCurr != fgkDataEndmarker)
          fPayloadCurr++;
        count += fPayloadCurr - startPos;
-       
+
        // feeding TRAP config
        // feeding TRAP config
-       AliTRDtrapConfig *trapcfg = AliTRDtrapConfig::Instance();
-       trapcfg->ReadPackedConfig(fCurrHC, startPos, fPayloadCurr - startPos);
+       AliTRDtrapConfig *trapcfg = AliTRDcalibDB::Instance()->GetTrapConfig();
+       AliTRDmcmSim::ReadPackedConfig(trapcfg, fCurrHC, startPos, fPayloadCurr - startPos);
       }
       else {
        Int_t tpmode = fCurrMajor & 0x7;
        AliDebug(1, Form("Checking testpattern (mode %i) data", tpmode));
       }
       else {
        Int_t tpmode = fCurrMajor & 0x7;
        AliDebug(1, Form("Checking testpattern (mode %i) data", tpmode));
-       ReadTPData(tpmode);
+       count += ReadTPData(tpmode);
       }
     }
       }
     }
-    else if (fCurrMajor & 0x20) {
-      AliDebug(1, "This is a zs event");
-      count += ReadZSData();
-    }
     else {
     else {
-      AliDebug(1, "This is a nozs event");
-      count += ReadNonZSData();
+      // reading real data
+      if (fDigitsManager) {
+       if ((fAdcArray = fDigitsManager->GetDigits(det))) {
+         //fAdcArray->Expand();
+         if (fAdcArray->GetNtime() != fCurrNtimebins)
+           fAdcArray->Allocate(16, 144, fCurrNtimebins);
+       }
+       else {
+         LinkError(kNoDigits);
+       }
+
+       if (!fDigitsParam) {
+         fDigitsParam = fDigitsManager->GetDigitsParam();
+       }
+       if (fDigitsParam) {
+         fDigitsParam->SetPretriggerPhase(det, fCurrPtrgPhase);
+         fDigitsParam->SetNTimeBins(det, fCurrNtimebins);
+         fDigitsParam->SetADCbaseline(det, 10);
+       }
+
+       if (fDigitsManager->UsesDictionaries()) {
+         fDigitsManager->GetDictionary(det, 0)->Reset();
+         fDigitsManager->GetDictionary(det, 1)->Reset();
+         fDigitsManager->GetDictionary(det, 2)->Reset();
+       }
+
+       if ((fSignalIndex = fDigitsManager->GetIndexes(det))) {
+         fSignalIndex->SetSM(fCurrSm);
+         fSignalIndex->SetStack(fCurrStack);
+         fSignalIndex->SetLayer(fCurrLayer);
+         fSignalIndex->SetDetNumber(det);
+         if (!fSignalIndex->IsAllocated())
+           fSignalIndex->Allocate(16, 144, fCurrNtimebins);
+       }
+
+       if (fCurrMajor & 0x20) {
+         AliDebug(1, "This is a zs event");
+         count += ReadZSData();
+       }
+       else {
+         AliDebug(1, "This is a nozs event");
+         count += ReadNonZSData();
+       }
+      }
+      else {
+       // just read until data endmarkers
+       while (fPayloadCurr - fPayloadStart < fPayloadSize &&
+              *fPayloadCurr != fgkDataEndmarker)
+         fPayloadCurr++;
+      }
     }
   }
   else {
     }
   }
   else {
-    AliError(LinkError(kInvalidDetector, Form("%i", det)));
+    LinkError(kInvalidDetector, "%i", det);
     while (fPayloadCurr - fPayloadStart < fPayloadSize &&
           *fPayloadCurr != fgkDataEndmarker)
       fPayloadCurr++;
   }
     while (fPayloadCurr - fPayloadStart < fPayloadSize &&
           *fPayloadCurr != fgkDataEndmarker)
       fPayloadCurr++;
   }
-  
-  fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytes     += (fPayloadCurr - startPosLink) * sizeof(UInt_t);
-  fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytesRead += count * sizeof(UInt_t);
-  fStats.fStatsSector[fCurrSm].fBytesRead                      += count * sizeof(UInt_t);
-  fStats.fBytesRead                                            += count * sizeof(UInt_t);
+
+  if (fCurrSm > -1 && fCurrSm < 18) {
+    fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytes     += (fPayloadCurr - startPosLink) * sizeof(UInt_t);
+    fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytesRead += count * sizeof(UInt_t);
+    fStats.fStatsSector[fCurrSm].fBytesRead                      += count * sizeof(UInt_t);
+    fStats.fBytesRead                                            += count * sizeof(UInt_t);
+  }
+
+  if ((fErrorFlags & kDiscardHC) && fAdcArray)
+    fAdcArray->SetDataInvalid(); // invalidate the data
 
   return count;
 }
 
   return count;
 }
@@ -554,31 +1370,34 @@ Int_t AliTRDrawStream::ReadTracklets()
 {
   // read the tracklets from one HC
 
 {
   // read the tracklets from one HC
 
-  fTrackletArray->Clear();
+  Int_t nTracklets = 0;
 
   UInt_t *start = fPayloadCurr;
 
   UInt_t *start = fPayloadCurr;
-  while (*(fPayloadCurr) != fgkTrackletEndmarker && 
-        fPayloadCurr - fPayloadStart < fPayloadSize) {
-
-    new ((*fTrackletArray)[fTrackletArray->GetEntriesFast()]) AliTRDtrackletWord(*(fPayloadCurr));
+  while (*(fPayloadCurr) != fgkTrackletEndmarker &&
+        *(fPayloadCurr) != fgkStackEndmarker[0] &&
+        *(fPayloadCurr) != fgkStackEndmarker[1] &&
+        fPayloadCurr - fPayloadStart < (fPayloadSize - 1)) {
+    ++nTracklets;
+    if (fTracklets)
+      new ((*fTracklets)[fTracklets->GetEntriesFast()]) AliTRDtrackletWord(*(fPayloadCurr), fCurrHC);
 
     fPayloadCurr++;
   }
 
 
     fPayloadCurr++;
   }
 
-  if (fTrackletArray->GetEntriesFast() > 0) {
-    AliDebug(1, Form("Found %i tracklets in %i %i %i (ev. %i)", fTrackletArray->GetEntriesFast(), 
-                    fCurrSm, fCurrSlot, fCurrLink, fRawReader->GetEventIndex()));
-    fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNTracklets += fTrackletArray->GetEntriesFast();
-    fStats.fStatsSector[fCurrSm].fNTracklets                      += fTrackletArray->GetEntriesFast();
-    if (fTrackletTree)
-      fTrackletTree->Fill();
+  if (nTracklets > 0) {
+    AliDebug(1, Form("Found %i tracklets in %i %i %i (ev. %i)", nTracklets,
+                    (fCurrEquipmentId-kDDLOffset), fCurrSlot, fCurrLink, fRawReader->GetEventIndex()));
+    if (fCurrSm > -1 && fCurrSm < 18) {
+      fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNTracklets += nTracklets;
+      fStats.fStatsSector[fCurrSm].fNTracklets                      += nTracklets;
+    }
   }
 
   // loop over remaining tracklet endmarkers
   }
 
   // loop over remaining tracklet endmarkers
-  while ((*(fPayloadCurr) == fgkTrackletEndmarker && 
-         fPayloadCurr - fPayloadStart < fPayloadSize)) 
+  while ((*(fPayloadCurr) == fgkTrackletEndmarker &&
+         fPayloadCurr - fPayloadStart < fPayloadSize))
     fPayloadCurr++;
     fPayloadCurr++;
-  
+
   return fPayloadCurr - start;
 }
 
   return fPayloadCurr - start;
 }
 
@@ -587,10 +1406,15 @@ Int_t AliTRDrawStream::ReadHcHeader()
   // read and parse the HC header of one HC
   // and store the information in the corresponding variables
 
   // read and parse the HC header of one HC
   // and store the information in the corresponding variables
 
+  AliDebug(1, Form("HC header: 0x%08x", *fPayloadCurr));
   UInt_t *start = fPayloadCurr;
   // check not to be at the data endmarker
   UInt_t *start = fPayloadCurr;
   // check not to be at the data endmarker
-  if (*fPayloadCurr == fgkDataEndmarker)
+  if (*fPayloadCurr == fgkDataEndmarker ||
+      *(fPayloadCurr) == fgkStackEndmarker[0] ||
+      *(fPayloadCurr) == fgkStackEndmarker[1]) {
+    LinkError(kHCmismatch, "found endmarker where HC header should be");
     return 0;
     return 0;
+  }
 
   fCurrSpecial    = (*fPayloadCurr >> 31) & 0x1;
   fCurrMajor      = (*fPayloadCurr >> 24) & 0x7f;
 
   fCurrSpecial    = (*fPayloadCurr >> 31) & 0x1;
   fCurrMajor      = (*fPayloadCurr >> 24) & 0x7f;
@@ -602,29 +1426,31 @@ Int_t AliTRDrawStream::ReadHcHeader()
   fCurrSide       = (*fPayloadCurr >> 2) & 0x1;
   fCurrCheck      = (*fPayloadCurr) & 0x3;
 
   fCurrSide       = (*fPayloadCurr >> 2) & 0x1;
   fCurrCheck      = (*fPayloadCurr) & 0x3;
 
-  if (fCurrSm != (((Int_t) fCurrEquipmentId) - 1024) || 
-      fCurrStack != fCurrSlot || 
-      fCurrLayer != fCurrLink / 2 || 
-      fCurrSide != fCurrLink % 2) {
-    AliError(LinkError(kHCmismatch,
-                      Form("HC: %i, %i, %i, %i\n 0x%08x 0x%08x 0x%08x 0x%08x", 
-                           fCurrSm, fCurrStack, fCurrLayer, fCurrSide,
-                           fPayloadCurr[0], fPayloadCurr[1], fPayloadCurr[2], fPayloadCurr[3]) ));
+  if ((fCurrSm != (((Int_t) fCurrEquipmentId) - kDDLOffset)) ||
+      (fCurrStack != fCurrSlot) ||
+      (fCurrLayer != fCurrLink / 2) ||
+      (fCurrSide != fCurrLink % 2)) {
+    LinkError(kHCmismatch,
+             "HC: %i, %i, %i, %i\n 0x%08x 0x%08x 0x%08x 0x%08x",
+             fCurrSm, fCurrStack, fCurrLayer, fCurrSide,
+             fPayloadCurr[0], fPayloadCurr[1], fPayloadCurr[2], fPayloadCurr[3]);
   }
   if (fCurrCheck != 0x1) {
   }
   if (fCurrCheck != 0x1) {
-    AliError(LinkError(kHCcheckFailed));
+    LinkError(kHCcheckFailed);
   }
   }
-  
+
   if (fCurrAddHcWords > 0) {
     fCurrNtimebins = (fPayloadCurr[1] >> 26) & 0x3f;
   if (fCurrAddHcWords > 0) {
     fCurrNtimebins = (fPayloadCurr[1] >> 26) & 0x3f;
-    fCurrBC = (fPayloadCurr[1] >> 10) & 0xffff;
+#ifdef TRD_RAW_DEBUG
+    fCurrBC[fCurrHC] = (fPayloadCurr[1] >> 10) & 0xffff;
+#endif
     fCurrPtrgCnt = (fPayloadCurr[1] >> 6) & 0xf;
     fCurrPtrgPhase = (fPayloadCurr[1] >> 2) & 0xf;
   }
     fCurrPtrgCnt = (fPayloadCurr[1] >> 6) & 0xf;
     fCurrPtrgPhase = (fPayloadCurr[1] >> 2) & 0xf;
   }
-  
+
   fPayloadCurr += 1 + fCurrAddHcWords;
   fPayloadCurr += 1 + fCurrAddHcWords;
-  
-  return (fPayloadCurr - start) / sizeof(UInt_t);
+
+  return (fPayloadCurr - start);
 }
 
 Int_t AliTRDrawStream::ReadTPData(Int_t mode)
 }
 
 Int_t AliTRDrawStream::ReadTPData(Int_t mode)
@@ -633,6 +1459,7 @@ Int_t AliTRDrawStream::ReadTPData(Int_t mode)
   // evcnt checking missing
   Int_t cpu = 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};
   // evcnt checking missing
   Int_t cpu = 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};
+  Int_t evno  = -1;
   Int_t evcnt = 0;
   Int_t count = 0;
   Int_t mcmcount = -1;
   Int_t evcnt = 0;
   Int_t count = 0;
   Int_t mcmcount = -1;
@@ -646,34 +1473,54 @@ Int_t AliTRDrawStream::ReadTPData(Int_t mode)
 
   UInt_t* start = fPayloadCurr;
 
 
   UInt_t* start = fPayloadCurr;
 
-  while (*(fPayloadCurr) != fgkDataEndmarker && 
+  while (*(fPayloadCurr) != fgkDataEndmarker &&
         fPayloadCurr - fPayloadStart < fPayloadSize - 1) {
 
     // ----- Checking MCM Header -----
         fPayloadCurr - fPayloadStart < fPayloadSize - 1) {
 
     // ----- Checking MCM Header -----
-    AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
+    AliDebug(2, DumpMcmHeader("MCM header: ", *fPayloadCurr));
+    UInt_t *startPosMCM = fPayloadCurr;
     mcmcount++;
     mcmcount++;
-    
+
     // ----- checking for proper readout order - ROB -----
     // ----- checking for proper readout order - ROB -----
+    fCurrRobPos = ROB(*fPayloadCurr);
     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
+      if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
+       lastmcmpos = -1;
       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
     }
     else {
       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
     }
     else {
-      AliError(ROBError(kPosUnexp));
+      ROBError(kPosUnexp, Form("#%i after #%i in readout order", GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos));
     }
     }
-    fCurrRobPos = ROB(*fPayloadCurr);
-    
+
     // ----- checking for proper readout order - MCM -----
     // ----- checking for proper readout order - MCM -----
-    if (GetMCMReadoutPos(MCM(*fPayloadCurr)) >= (lastmcmpos + 1) % 16) {
+    fCurrMcmPos = MCM(*fPayloadCurr);
+    if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
       lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
     }
     else {
       lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
     }
     else {
-      AliError(MCMError(kPosUnexp));
+      MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
+    }
+
+    if (EvNo(*fPayloadCurr) != (evno & 0xfffff)) {
+      if (evno == -1) {
+       evno = EvNo(*fPayloadCurr);
+      }
+      else {
+       MCMError(kEvCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
+#ifdef TRD_RAW_DEBUG
+       if (fCurrL0offset[fCurrHC/2] != 0)
+         LinkError(kEvCntMismatch, "offset for %i %i %i changed from %i to %i = %i - %i",
+                   fCurrEquipmentId, fCurrSlot, fCurrLink/2, fCurrL0offset[fCurrHC/2],
+                   EvNo(*fPayloadCurr) - fCurrL0Count[fCurrEquipmentId-kDDLOffset],
+                   EvNo(*fPayloadCurr), fCurrL0Count[fCurrEquipmentId-kDDLOffset]);
+       fCurrL0offset[fCurrHC/2] = EvNo(*fPayloadCurr) - fCurrL0Count[fCurrEquipmentId-kDDLOffset];
+       evno = fCurrL0Count[fCurrEquipmentId-kDDLOffset] + fCurrL0offset[fCurrHC/2];
+#endif
+      }
     }
     }
-    fCurrMcmPos = MCM(*fPayloadCurr);
-    
 
     fPayloadCurr++;
 
     fPayloadCurr++;
-    
+
     evcnt = 0x3f & *fPayloadCurr >> 26;
     cpu = -1;
     channelcount = 0;
     evcnt = 0x3f & *fPayloadCurr >> 26;
     cpu = -1;
     channelcount = 0;
@@ -684,13 +1531,18 @@ Int_t AliTRDrawStream::ReadTPData(Int_t mode)
        expadcval = (1 << 9) | (fCurrRobPos << 6) | (fCurrMcmPos << 2) | cpu;
        wordcount = 0;
       }
        expadcval = (1 << 9) | (fCurrRobPos << 6) | (fCurrMcmPos << 2) | cpu;
        wordcount = 0;
       }
-      
+
       while (count < 10) {
       while (count < 10) {
+       if (*fPayloadCurr == fgkDataEndmarker) {
+         MCMError(kMissTpData);
+         return (fPayloadCurr - start);
+       }
+
        if (channelcount % 2 == 0)
          expword = 0x3;
        if (channelcount % 2 == 0)
          expword = 0x3;
-       else 
+       else
          expword = 0x2;
          expword = 0x2;
-       
+
        if (mode == 1) {
          // ----- TP 1 -----
          expword |= expadcval << 2;
        if (mode == 1) {
          // ----- TP 1 -----
          expword |= expadcval << 2;
@@ -702,44 +1554,58 @@ Int_t AliTRDrawStream::ReadTPData(Int_t mode)
        }
        else if (mode == 2) {
          // ----- TP 2 ------
        }
        else if (mode == 2) {
          // ----- TP 2 ------
-         expword = ((0x3f & evcnt) << 26) | ((fCurrSm + 1) << 21) | ((fCurrLayer + 1) << 18) | 
-           ((fCurrStack + 1) << 15) | 
-           (fCurrRobPos << 12) | (fCurrMcmPos << 8) | (cpu << 6) | (wordcount + 1); 
+         expword = ((0x3f & evcnt) << 26) | ((fCurrSm + 1) << 21) | ((fCurrLayer + 1) << 18) |
+           ((fCurrStack + 1) << 15) |
+           (fCurrRobPos << 12) | (fCurrMcmPos << 8) | (cpu << 6) | (wordcount + 1);
        }
        else if (mode == 3) {
          // ----- TP 3 -----
        }
        else if (mode == 3) {
          // ----- TP 3 -----
-         expword = ((0xfff & evcnt) << 20) | (fCurrSm << 15) | (fCurrLink/2 << 12) | (fCurrStack << 9) | 
-           (fCurrRobPos << 6) | (fCurrMcmPos << 2) | (cpu << 0); 
+         expword = ((0xfff & evcnt) << 20) | (fCurrSm << 15) | (fCurrLink/2 << 12) | (fCurrStack << 9) |
+           (fCurrRobPos << 6) | (fCurrMcmPos << 2) | (cpu << 0);
        }
        else {
          expword = 0;
        }
        else {
          expword = 0;
-         AliError(LinkError(kTPmodeInvalid, "Just reading"));
+         LinkError(kTPmodeInvalid, "Just reading");
        }
 
        diff = *fPayloadCurr ^ expword;
        }
 
        diff = *fPayloadCurr ^ expword;
+       AliDebug(11, Form("Comparing ch %2i, word %2i (cpu %i): 0x%08x <-> 0x%08x",
+                         channelcount, wordcount, cpu, *fPayloadCurr, expword));
+
        if (diff != 0) {
        if (diff != 0) {
-         AliError(MCMError(kTPmismatch,
-                           Form("Seen 0x%08x, expected 0x%08x, diff: 0x%08x (0x%02x)", 
-                                *fPayloadCurr, expword, diff, 0xff & (diff | diff >> 8 | diff >> 16 | diff >> 24)) ));
+         MCMError(kTPmismatch,
+                  "Seen 0x%08x, expected 0x%08x, diff: 0x%08x, 0x%04x, 0x%02x - word %2i (cpu %i, ch %i)",
+                  *fPayloadCurr, expword, diff,
+                  0xffff & (diff | diff >> 16),
+                  0xff & (diff | diff >> 8 | diff >> 16 | diff >> 24),
+                  wordcount, cpu, channelcount);;
        }
        fPayloadCurr++;
        count++;
        wordcount++;
        }
        fPayloadCurr++;
        count++;
        wordcount++;
+       if (*fPayloadCurr == fgkDataEndmarker)
+         return (fPayloadCurr - start);
       }
       channelcount++;
     }
     // continue with next MCM
       }
       channelcount++;
     }
     // continue with next MCM
+
+    if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
+      AliInfo(DumpRaw(Form("Event %i: Det %3i ROB %i MCM %2i", fRawReader->GetEventIndex(), fCurrHC/2, fCurrRobPos, fCurrMcmPos),
+                     startPosMCM, fPayloadCurr - startPosMCM));
+    }
+
   }
   }
-  return fPayloadCurr - start; 
+  return fPayloadCurr - start;
 }
 
 
 Int_t AliTRDrawStream::ReadZSData()
 {
   // read the zs data from one link from the current reading position
 }
 
 
 Int_t AliTRDrawStream::ReadZSData()
 {
   // read the zs data from one link from the current reading position
-  
+
   UInt_t *start = fPayloadCurr;
   UInt_t *start = fPayloadCurr;
-  
+
   Int_t mcmcount = 0;
   Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
   Int_t channelcount = 0;
   Int_t mcmcount = 0;
   Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
   Int_t channelcount = 0;
@@ -753,62 +1619,96 @@ Int_t AliTRDrawStream::ReadZSData()
   Int_t lastrobpos = -1;
 
   if (fCurrNtimebins != fNtimebins) {
   Int_t lastrobpos = -1;
 
   if (fCurrNtimebins != fNtimebins) {
-    if (fNtimebins > 0) 
-      AliError(LinkError(kNtimebinsChanged,
-                        Form("No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins) ));
+    if (fNtimebins > 0)
+      LinkError(kNtimebinsChanged,
+               "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
     fNtimebins = fCurrNtimebins;
   }
     fNtimebins = fCurrNtimebins;
   }
-  
+
   timebins = fNtimebins;
   timebins = fNtimebins;
-  
-  while (*(fPayloadCurr) != fgkDataEndmarker && 
+
+  while (*(fPayloadCurr) != fgkDataEndmarker &&
+        *(fPayloadCurr) != fgkStackEndmarker[0] &&
+        *(fPayloadCurr) != fgkStackEndmarker[1] &&
         fPayloadCurr - fPayloadStart < fPayloadSize) {
         fPayloadCurr - fPayloadStart < fPayloadSize) {
-    
+
     // ----- Checking MCM Header -----
     // ----- Checking MCM Header -----
-    AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
+    AliDebug(2, DumpMcmHeader("MCM header: ", *fPayloadCurr));
     UInt_t *startPosMCM = fPayloadCurr;
     UInt_t *startPosMCM = fPayloadCurr;
-    
+
     // ----- checking for proper readout order - ROB -----
     // ----- checking for proper readout order - ROB -----
+    fCurrRobPos = ROB(*fPayloadCurr);
     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
+      if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
+       lastmcmpos = -1;
       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
     }
     else {
       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
     }
     else {
-      AliError(ROBError(kPosUnexp));
+      ROBError(kPosUnexp, Form("#%i after #%i and #%i in readout order",
+                              GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos, GetROBReadoutPos(fCurrRobPos)));
     }
     }
-    fCurrRobPos = ROB(*fPayloadCurr);
-    
+
     // ----- checking for proper readout order - MCM -----
     // ----- checking for proper readout order - MCM -----
+    fCurrMcmPos = MCM(*fPayloadCurr);
     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
     if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
-      lastmcmpos = GetMCMReadoutPos(lastmcmpos);
+      lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
     }
     else {
     }
     else {
-      AliError(MCMError(kPosUnexp));
+      MCMError(kPosUnexp, Form("#%i after #%i and #%i in readout order",
+                              GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos, GetMCMReadoutPos(fCurrMcmPos)));
     }
     }
-    fCurrMcmPos = MCM(*fPayloadCurr);
-    
-    if (EvNo(*fPayloadCurr) != evno) {
-      if (evno == -1)
+
+#ifdef TRD_RAW_DEBUG
+    if (fCurrL0Count[fCurrEquipmentId-kDDLOffset] > 0) {
+      evno = fCurrL0Count[fCurrEquipmentId-kDDLOffset] + fCurrL0offset[fCurrHC/2];
+    }
+    fCurrEvCount[fCurrEquipmentId-kDDLOffset] = EvNo(*fPayloadCurr);
+#endif
+
+    if (EvNo(*fPayloadCurr) != (evno & 0xfffff)) {
+      if (evno == -1) {
        evno = EvNo(*fPayloadCurr);
        evno = EvNo(*fPayloadCurr);
+      }
       else {
       else {
-       AliDebug(1, MCMError(kPtrgCntMismatch,
-                            Form("%i <-> %i", evno, EvNo(*fPayloadCurr)) ));
+       MCMError(kEvCntMismatch, "exp <-> SM: %i <-> %i", evno & 0xfffff, EvNo(*fPayloadCurr));
+#ifdef TRD_RAW_DEBUG
+       Int_t prevOffset = fCurrL0offset[fCurrHC/2];
+       fCurrL0offset[fCurrHC/2] = (- fCurrL0Count[fCurrEquipmentId-kDDLOffset] + EvNo(*fPayloadCurr)) % (1 << 20);
+       if (fCurrL0offset[fCurrHC/2] < 0)
+         fCurrL0offset[fCurrHC/2] += 0xfffff;
+       evno = (fCurrL0Count[fCurrEquipmentId-kDDLOffset] + fCurrL0offset[fCurrHC/2]) & 0xfffff;
+       if (prevOffset != 0)
+         LinkError(kEvCntMismatch, "offset for %i %i %i changed from %i to %i = %i - %i",
+                   fCurrEquipmentId, fCurrSlot, fCurrLink/2,
+                   prevOffset,
+                   fCurrL0offset[fCurrHC/2],
+                   fCurrL0Count[fCurrEquipmentId-kDDLOffset],
+                   EvNo(*fPayloadCurr));
+#endif
       }
     }
     Int_t adccoloff = AdcColOffset(*fPayloadCurr);
     Int_t padcoloff = PadColOffset(*fPayloadCurr);
     Int_t row = Row(*fPayloadCurr);
     fPayloadCurr++;
       }
     }
     Int_t adccoloff = AdcColOffset(*fPayloadCurr);
     Int_t padcoloff = PadColOffset(*fPayloadCurr);
     Int_t row = Row(*fPayloadCurr);
     fPayloadCurr++;
-    
+
+    if ((row > 11) && (fCurrStack == 2)) {
+      MCMError(kInvalidPadRow, "Data in padrow > 11 for stack 2");
+    }
+
+    if (fErrorFlags & (kDiscardHC | kDiscardDDL))
+      break;
+
     // ----- Reading ADC channels -----
     // ----- Reading ADC channels -----
-    AliDebug(2, Form("ADC mask: 0x%08x", *fPayloadCurr));
-    
+    AliDebug(2, DumpAdcMask("ADC mask: ", *fPayloadCurr));
+
     // ----- analysing the ADC mask -----
     channelcount = 0;
     channelcountExp = GetNActiveChannelsFromMask(*fPayloadCurr);
     channelcountMax = GetNActiveChannels(*fPayloadCurr);
     Int_t channelmask = GetActiveChannels(*fPayloadCurr);
     Int_t channelno = -1;
     // ----- analysing the ADC mask -----
     channelcount = 0;
     channelcountExp = GetNActiveChannelsFromMask(*fPayloadCurr);
     channelcountMax = GetNActiveChannels(*fPayloadCurr);
     Int_t channelmask = GetActiveChannels(*fPayloadCurr);
     Int_t channelno = -1;
-    fPayloadCurr++; 
+    fPayloadCurr++;
 
     if (channelcountExp != channelcountMax) {
       if (channelcountExp > channelcountMax) {
 
     if (channelcountExp != channelcountMax) {
       if (channelcountExp > channelcountMax) {
@@ -816,104 +1716,113 @@ Int_t AliTRDrawStream::ReadZSData()
        channelcountExp = channelcountMax;
        channelcountMax = temp;
       }
        channelcountExp = channelcountMax;
        channelcountMax = temp;
       }
-      while (channelcountExp < channelcountMax && channelcountExp < 21 && 
+      while (channelcountExp < channelcountMax && channelcountExp < 21 &&
             fPayloadCurr - fPayloadStart < fPayloadSize - 10 * channelcountExp - 1) {
             fPayloadCurr - fPayloadStart < fPayloadSize - 10 * channelcountExp - 1) {
-       AliDebug(1, MCMError(kAdcMaskInconsistent,
-                         Form("Possible MCM-H: 0x%08x, possible ADC-mask: 0x%08x", 
-                              *(fPayloadCurr + 10 * channelcountExp), 
-                              *(fPayloadCurr + 10 * channelcountExp + 1) ) ));
-       if (!CouldBeMCMhdr( *(fPayloadCurr + 10 * channelcountExp)) && !CouldBeADCmask( *(fPayloadCurr + 10 * channelcountExp + 1))) 
+       MCMError(kAdcMaskInconsistent,
+                "Possible MCM-H: 0x%08x, possible ADC-mask: 0x%08x",
+                *(fPayloadCurr + 10 * channelcountExp),
+                *(fPayloadCurr + 10 * channelcountExp + 1) );
+       if (!CouldBeMCMhdr( *(fPayloadCurr + 10 * channelcountExp)) && !CouldBeADCmask( *(fPayloadCurr + 10 * channelcountExp + 1)))
          channelcountExp++;
        else {
          break;
        }
       }
          channelcountExp++;
        else {
          break;
        }
       }
-      AliDebug(1, MCMError(kAdcMaskInconsistent,
-                          Form("Inconsistency in no. of active channels: Counter: %i, Mask: %i, chosen: %i!", 
-                               GetNActiveChannels(fPayloadCurr[-1]), GetNActiveChannelsFromMask(fPayloadCurr[-1]), channelcountExp) ));
+      MCMError(kAdcMaskInconsistent,
+              "Inconsistency in no. of active channels: Counter: %i, Mask: %i, chosen: %i!",
+              GetNActiveChannels(fPayloadCurr[-1]), GetNActiveChannelsFromMask(fPayloadCurr[-1]), channelcountExp);
     }
     }
-    AliDebug(2, Form("expecting %i active channels, timebins: %i", channelcountExp, fCurrNtimebins));
-    
+    AliDebug(2, Form("expecting %i active channels, %i timebins", channelcountExp, fCurrNtimebins));
+
     // ----- reading marked ADC channels -----
     while (channelcount < channelcountExp && *(fPayloadCurr) != fgkDataEndmarker) {
     // ----- reading marked ADC channels -----
     while (channelcount < channelcountExp && *(fPayloadCurr) != fgkDataEndmarker) {
-      if (channelno < 21)
+      if (channelno < 20)
        channelno++;
        channelno++;
-      while (channelno < 21 && (channelmask & 1 << channelno) == 0)
+      while (channelno < 20 && (channelmask & 1 << channelno) == 0)
        channelno++;
        channelno++;
-      
+
       if (fCurrNtimebins > 30) {
        currentTimebin = ((*fPayloadCurr >> 2) & 0x3f);
        timebins = ((*fPayloadCurr >> 8) & 0xf) * 3;
       if (fCurrNtimebins > 30) {
        currentTimebin = ((*fPayloadCurr >> 2) & 0x3f);
        timebins = ((*fPayloadCurr >> 8) & 0xf) * 3;
-      } 
+      }
       else {
        currentTimebin = 0;
       }
       else {
        currentTimebin = 0;
       }
-      
+
       adcwc = 0;
       adcwc = 0;
-      AliDebug(2, Form("Now looking %i words", timebins / 3));
+      Int_t nADCwords = (timebins + 2) / 3;
+      AliDebug(3, Form("Now reading %i words for channel %2i", nADCwords, channelno));
       Int_t adccol = adccoloff - channelno;
       Int_t padcol = padcoloff - channelno;
       Int_t adccol = adccoloff - channelno;
       Int_t padcol = padcoloff - channelno;
-//      if (adccol < 3 || adccol > 165) 
-//     AliInfo(Form("writing channel %i of det %3i %i:%2i to adcrow/-col: %i/%i padcol: %i", 
+//      if (adccol < 3 || adccol > 165)
+//     AliInfo(Form("writing channel %i of det %3i %i:%2i to adcrow/-col: %i/%i padcol: %i",
 //                  channelno, fCurrHC/2, fCurrRobPos, fCurrMcmPos, row, adccol, padcol));
 
 //                  channelno, fCurrHC/2, fCurrRobPos, fCurrMcmPos, row, adccol, padcol));
 
-      while (adcwc < timebins / 3 && 
-            *(fPayloadCurr) != fgkDataEndmarker && 
-            fPayloadCurr - fPayloadStart < fPayloadSize) {
+      while ((adcwc < nADCwords) &&
+            (*(fPayloadCurr) != fgkDataEndmarker) &&
+            (fPayloadCurr - fPayloadStart < fPayloadSize)) {
        int check = 0x3 & *fPayloadCurr;
        if (channelno % 2 != 0) { // odd channel
          if (check != 0x2 && channelno < 21) {
        int check = 0x3 & *fPayloadCurr;
        if (channelno % 2 != 0) { // odd channel
          if (check != 0x2 && channelno < 21) {
-           AliError(MCMError(kAdcCheckInvalid,
-                             Form("%i for %2i. ADC word in odd channel %i", 
-                                  check, adcwc+1, channelno) ));
+           MCMError(kAdcCheckInvalid,
+                    "%i for %2i. ADC word in odd channel %i",
+                    check, adcwc+1, channelno);
          }
        }
        else {                  // even channel
          if (check != 0x3 && channelno < 21) {
          }
        }
        else {                  // even channel
          if (check != 0x3 && channelno < 21) {
-           AliError(MCMError(kAdcCheckInvalid,
-                             Form("%i for %2i. ADC word in even channel %i", 
-                                  check, adcwc+1, channelno) ));
+           MCMError(kAdcCheckInvalid,
+                    "%i for %2i. ADC word in even channel %i",
+                    check, adcwc+1, channelno);
          }
        }
          }
        }
-       
-       // filling the actual timebin data
-       int tb2 = 0x3ff & *fPayloadCurr >> 22;
-       int tb1 = 0x3ff & *fPayloadCurr >> 12;
-       int tb0 = 0x3ff & *fPayloadCurr >> 2;
-       if (adcwc != 0 || fCurrNtimebins <= 30) 
-         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
-       else
-         tb0 = -1;
-       fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
-       fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
-       
+
+       if ((fErrorFlags & kDiscardMCM) == 0) {
+         // filling the actual timebin data
+         int tb2 = 0x3ff & (*fPayloadCurr >> 22);
+         int tb1 = 0x3ff & (*fPayloadCurr >> 12);
+         int tb0 = 0x3ff & (*fPayloadCurr >>  2);
+         if (adcwc != 0 || fCurrNtimebins <= 30)
+           fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
+         else
+           tb0 = -1;
+         if (currentTimebin < fCurrNtimebins)
+           fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
+         if (currentTimebin < fCurrNtimebins)
+           fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
+       }
+
        adcwc++;
        fPayloadCurr++;
       }
        adcwc++;
        fPayloadCurr++;
       }
-      
-      if (adcwc != timebins / 3) 
-       AliError(MCMError(kAdcDataAbort));
-      
-      // adding index 
+
+      if (adcwc != nADCwords)
+       MCMError(kAdcDataAbort);
+
+      // adding index
       if (padcol > 0 && padcol < 144) {
        fSignalIndex->AddIndexRC(row, padcol);
       }
       if (padcol > 0 && padcol < 144) {
        fSignalIndex->AddIndexRC(row, padcol);
       }
-      
+
       channelcount++;
     }
 
       channelcount++;
     }
 
-    fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNChannels += channelcount;
-    fStats.fStatsSector[fCurrSm].fNChannels                      += channelcount;
+    if (fCurrSm > -1 && fCurrSm < 18) {
+      fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNChannels += channelcount;
+      fStats.fStatsSector[fCurrSm].fNChannels                      += channelcount;
+    }
     if (channelcount != channelcountExp)
     if (channelcount != channelcountExp)
-      AliDebug(1, MCMError(kAdcChannelsMiss));
-    
+      MCMError(kAdcChannelsMiss);
+
     mcmcount++;
     mcmcount++;
-    fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNMCMs++;
-    fStats.fStatsSector[fCurrSm].fNMCMs++;
+    if (fCurrSm > -1 && fCurrSm < 18) {
+      fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNMCMs++;
+      fStats.fStatsSector[fCurrSm].fNMCMs++;
+    }
 
     if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
 
     if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
-      DumpRaw(Form("Det %3i ROB %i MCM %2i", fCurrHC/2, fCurrRobPos, fCurrMcmPos),
-             startPosMCM, fPayloadCurr - startPosMCM);
+      AliInfo(DumpRaw(Form("Event %i: Det %3i ROB %i MCM %2i", fRawReader->GetEventIndex(), fCurrHC/2, fCurrRobPos, fCurrMcmPos),
+                     startPosMCM, fPayloadCurr - startPosMCM));
     }
 
     // continue with next MCM
     }
 
     // continue with next MCM
@@ -921,9 +1830,9 @@ Int_t AliTRDrawStream::ReadZSData()
 
   // check for missing MCMs (if header suppression is inactive)
   if (((fCurrMajor & 0x1) == 0) && (mcmcount != mcmcountExp)) {
 
   // check for missing MCMs (if header suppression is inactive)
   if (((fCurrMajor & 0x1) == 0) && (mcmcount != mcmcountExp)) {
-    AliError(LinkError(kMissMcmHeaders,
-                      Form("No. of MCM headers %i not as expected: %i", 
-                           mcmcount, mcmcountExp) ));
+    LinkError(kMissMcmHeaders,
+             "No. of MCM headers %i not as expected: %i",
+             mcmcount, mcmcountExp);
   }
 
   return (fPayloadCurr - start);
   }
 
   return (fPayloadCurr - start);
@@ -932,9 +1841,9 @@ Int_t AliTRDrawStream::ReadZSData()
 Int_t AliTRDrawStream::ReadNonZSData()
 {
   // read the non-zs data from one link from the current reading position
 Int_t AliTRDrawStream::ReadNonZSData()
 {
   // read the non-zs data from one link from the current reading position
-  
+
   UInt_t *start = fPayloadCurr;
   UInt_t *start = fPayloadCurr;
-  
+
   Int_t mcmcount = 0;
   Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
   Int_t channelcount = 0;
   Int_t mcmcount = 0;
   Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
   Int_t channelcount = 0;
@@ -947,47 +1856,58 @@ Int_t AliTRDrawStream::ReadNonZSData()
   Int_t lastrobpos = -1;
 
   if (fCurrNtimebins != fNtimebins) {
   Int_t lastrobpos = -1;
 
   if (fCurrNtimebins != fNtimebins) {
-    if (fNtimebins > 0) 
-      AliError(LinkError(kNtimebinsChanged,
-                        Form("No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins) ));
+    if (fNtimebins > 0)
+      LinkError(kNtimebinsChanged,
+               "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
     fNtimebins = fCurrNtimebins;
   }
     fNtimebins = fCurrNtimebins;
   }
-  
+
   timebins = fNtimebins;
   timebins = fNtimebins;
-  
-  while (*(fPayloadCurr) != fgkDataEndmarker && 
+
+  while (*(fPayloadCurr) != fgkDataEndmarker &&
         fPayloadCurr - fPayloadStart < fPayloadSize - 2) {
         fPayloadCurr - fPayloadStart < fPayloadSize - 2) {
-    
+
     // ----- Checking MCM Header -----
     AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
     // ----- Checking MCM Header -----
     AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
-    
+
     // ----- checking for proper readout order - ROB -----
     // ----- checking for proper readout order - ROB -----
+    fCurrRobPos = ROB(*fPayloadCurr);
     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
     if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
+      if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
+       lastmcmpos = -1;
       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
     }
     else {
       lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
     }
     else {
-      AliError(ROBError(kPosUnexp));
+      ROBError(kPosUnexp, Form("#%i after #%i in readout order", GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos));
     }
     }
-    fCurrRobPos = ROB(*fPayloadCurr);
-    
+
     // ----- checking for proper readout order - MCM -----
     // ----- checking for proper readout order - MCM -----
-    if (GetMCMReadoutPos(MCM(*fPayloadCurr)) >= (lastmcmpos + 1) % 16) {
-      lastmcmpos = GetMCMReadoutPos(*fPayloadCurr);
+    fCurrMcmPos = MCM(*fPayloadCurr);
+    if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
+      lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
     }
     else {
     }
     else {
-      AliError(MCMError(kPosUnexp));
+      MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
     }
     }
-    fCurrMcmPos = MCM(*fPayloadCurr);
-    
-    if (EvNo(*fPayloadCurr) != evno) {
-      if (evno == -1)
+
+    if (EvNo(*fPayloadCurr) != (evno & 0xfffff)) {
+      if (evno == -1) {
        evno = EvNo(*fPayloadCurr);
        evno = EvNo(*fPayloadCurr);
+      }
       else {
       else {
-       AliDebug(1, MCMError(kPtrgCntMismatch,
-                            Form("%i <-> %i", evno, EvNo(*fPayloadCurr)) ));
+       MCMError(kEvCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
+#ifdef TRD_RAW_DEBUG
+       if (fCurrL0offset[fCurrHC/2] != 0)
+         LinkError(kEvCntMismatch, "offset for %i %i %i changed from %i to %i = %i - %i",
+                   fCurrEquipmentId, fCurrSlot, fCurrLink/2, fCurrL0offset[fCurrHC/2],
+                   EvNo(*fPayloadCurr) - fCurrL0Count[fCurrEquipmentId-kDDLOffset],
+                   EvNo(*fPayloadCurr), fCurrL0Count[fCurrEquipmentId-kDDLOffset]);
+       fCurrL0offset[fCurrHC/2] = EvNo(*fPayloadCurr) - fCurrL0Count[fCurrEquipmentId-kDDLOffset];
+       evno = fCurrL0Count[fCurrEquipmentId-kDDLOffset] + fCurrL0offset[fCurrHC/2];
+#endif
       }
     }
       }
     }
-    
+
     channelcount = 0;
     channelcountExp = 21;
     int channelno = -1;
     channelcount = 0;
     channelcountExp = 21;
     int channelno = -1;
@@ -995,59 +1915,70 @@ Int_t AliTRDrawStream::ReadNonZSData()
     Int_t adccoloff = AdcColOffset(*fPayloadCurr);
     Int_t padcoloff = PadColOffset(*fPayloadCurr);
     Int_t row = Row(*fPayloadCurr);
     Int_t adccoloff = AdcColOffset(*fPayloadCurr);
     Int_t padcoloff = PadColOffset(*fPayloadCurr);
     Int_t row = Row(*fPayloadCurr);
-
     fPayloadCurr++;
 
     fPayloadCurr++;
 
+    if ((row > 11) && (fCurrStack == 2)) {
+      MCMError(kInvalidPadRow, "Data in padrow > 11 for stack 2");
+    }
+
+    if (fErrorFlags & (kDiscardHC | kDiscardDDL))
+      break;
+
     // ----- reading marked ADC channels -----
     // ----- reading marked ADC channels -----
-    while (channelcount < channelcountExp && 
+    while (channelcount < channelcountExp &&
           *(fPayloadCurr) != fgkDataEndmarker) {
           *(fPayloadCurr) != fgkDataEndmarker) {
-      if (channelno < 21)
+      if (channelno < 20)
        channelno++;
        channelno++;
-      
+
       currentTimebin = 0;
       currentTimebin = 0;
-      
+
       adcwc = 0;
       adcwc = 0;
-      AliDebug(2, Form("Now looking %i words", timebins / 3));
+      Int_t nADCwords = (timebins + 2) / 3;
+      AliDebug(2, Form("Now looking %i words", nADCwords));
       Int_t adccol = adccoloff - channelno;
       Int_t padcol = padcoloff - channelno;
       Int_t adccol = adccoloff - channelno;
       Int_t padcol = padcoloff - channelno;
-      while (adcwc < timebins / 3 && 
-            *(fPayloadCurr) != fgkDataEndmarker && 
-            fPayloadCurr - fPayloadStart < fPayloadSize) {
+      while ((adcwc < nADCwords) &&
+            (*(fPayloadCurr) != fgkDataEndmarker) &&
+            (fPayloadCurr - fPayloadStart < fPayloadSize)) {
        int check = 0x3 & *fPayloadCurr;
        if (channelno % 2 != 0) { // odd channel
          if (check != 0x2 && channelno < 21) {
        int check = 0x3 & *fPayloadCurr;
        if (channelno % 2 != 0) { // odd channel
          if (check != 0x2 && channelno < 21) {
-           AliError(MCMError(kAdcCheckInvalid,
-                             Form("%i for %2i. ADC word in odd channel %i", 
-                                  check, adcwc+1, channelno) ));
+           MCMError(kAdcCheckInvalid,
+                    "%i for %2i. ADC word in odd channel %i",
+                    check, adcwc+1, channelno);
          }
        }
        else {                  // even channel
          if (check != 0x3 && channelno < 21) {
          }
        }
        else {                  // even channel
          if (check != 0x3 && channelno < 21) {
-           AliError(MCMError(kAdcCheckInvalid,
-                             Form("%i for %2i. ADC word in even channel %i", 
-                                  check, adcwc+1, channelno) ));
+           MCMError(kAdcCheckInvalid,
+                    "%i for %2i. ADC word in even channel %i",
+                    check, adcwc+1, channelno);
          }
        }
          }
        }
-       
-       // filling the actual timebin data
-       int tb2 = 0x3ff & *fPayloadCurr >> 22;
-       int tb1 = 0x3ff & *fPayloadCurr >> 12;
-       int tb0 = 0x3ff & *fPayloadCurr >> 2;
-       if (adcwc != 0 || fCurrNtimebins <= 30) 
-         fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
-       else
-         tb0 = -1;
-       fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
-       fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
+
+       if ((fErrorFlags & kDiscardMCM) == 0) {
+         // filling the actual timebin data
+         int tb2 = 0x3ff & (*fPayloadCurr >> 22);
+         int tb1 = 0x3ff & (*fPayloadCurr >> 12);
+         int tb0 = 0x3ff & (*fPayloadCurr >>  2);
+         if (adcwc != 0 || fCurrNtimebins <= 30)
+           fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
+         else
+           tb0 = -1;
+         if (currentTimebin < fCurrNtimebins)
+           fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
+         if (currentTimebin < fCurrNtimebins)
+           fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
+       }
 
        adcwc++;
        fPayloadCurr++;
       }
 
 
        adcwc++;
        fPayloadCurr++;
       }
 
-      if (adcwc != timebins / 3) 
-       AliError(MCMError(kAdcDataAbort));
-      
-      // adding index 
+      if (adcwc != nADCwords)
+       MCMError(kAdcDataAbort);
+
+      // adding index
       if (padcol > 0 && padcol < 144) {
        fSignalIndex->AddIndexRC(row, padcol);
       }
       if (padcol > 0 && padcol < 144) {
        fSignalIndex->AddIndexRC(row, padcol);
       }
@@ -1056,138 +1987,246 @@ Int_t AliTRDrawStream::ReadNonZSData()
     }
 
     if (channelcount != channelcountExp)
     }
 
     if (channelcount != channelcountExp)
-      AliDebug(1, MCMError(kAdcChannelsMiss));
+      MCMError(kAdcChannelsMiss);
     mcmcount++;
     // continue with next MCM
   }
 
   // check for missing MCMs (if header suppression is inactive)
   if (mcmcount != mcmcountExp) {
     mcmcount++;
     // continue with next MCM
   }
 
   // check for missing MCMs (if header suppression is inactive)
   if (mcmcount != mcmcountExp) {
-    AliError(LinkError(kMissMcmHeaders,
-                      Form("%i not as expected: %i", mcmcount, mcmcountExp) ));
+    LinkError(kMissMcmHeaders,
+             "%i not as expected: %i", mcmcount, mcmcountExp);
   }
 
   return (fPayloadCurr - start);
 }
 
   }
 
   return (fPayloadCurr - start);
 }
 
-Bool_t AliTRDrawStream::ConnectTracklets(TTree *trklTree) 
+#ifdef TRD_RAW_CRC
+UShort_t AliTRDrawStream::CalcLinkChecksum(UInt_t *data, Int_t size)
 {
 {
-  fTrackletTree = trklTree;
-  if (!fTrackletTree) 
-    return kTRUE;
+  // calculate the CRC for the data from this link
+  // must not change the pointers to the data
+
+  // always count two endmarkers
+  Int_t nEndmarkers = 0;
+  for (Int_t i = 0; i < size; i++) {
+    if (data[size-1 - i] != fgkDataEndmarker)
+      break;
+    nEndmarkers++;
+  }
 
 
-  if (!fTrackletTree->GetBranch("hc")) 
-    fTrackletTree->Branch("hc", &fCurrHC, "hc/I");
-  else 
-    fTrackletTree->SetBranchAddress("hc", &fCurrHC);
+  size = size - (nEndmarkers-2);
 
 
-  if (!fTrackletTree->GetBranch("trkl")) 
-    fTrackletTree->Branch("trkl", &fTrackletArray);
-  else 
-    fTrackletTree->SetBranchAddress("trkl", &fTrackletArray);
+  boost::crc_optimal<16, 0x8005, 0, 0, false, false> checksumLink;
 
 
-  return kTRUE;
+  checksumLink.reset();
+  checksumLink.process_bytes(data, size*sizeof(UInt_t));
+  return checksumLink();
 }
 }
+#else
+UShort_t AliTRDrawStream::CalcLinkChecksum(UInt_t * /* data */, Int_t /* size */)
+{
+  // checksum calculation relies on boost,
+  // we return 0 if we cannot calculate it
+
+  AliError("Checksum calculation relies on boost CRC implementation!");
+
+  return 0;
+}
+#endif
+
+Int_t AliTRDrawStream::SeekNextStack()
+{
+  // proceed in raw data stream till the next stack
+
+  if (!fCurrStackEndmarkerAvail)
+    return 0;
+
+  UInt_t *start = fPayloadCurr;
+
+  // read until data endmarkers
+  while ((fPayloadCurr - fPayloadStart < fPayloadSize-1) &&
+        ((fPayloadCurr[0] != fgkStackEndmarker[0]) ||
+         (fPayloadCurr[1] != fgkStackEndmarker[1])))
+    fPayloadCurr++;
+
+  if ((fPayloadCurr - start) != 0)
+    StackError(kUnknown, "skipped %i words to reach stack endmarker", fPayloadCurr - start);
+
+  AliDebug(2, Form("stack endmarker: 0x%08x 0x%08x", fPayloadCurr[0], fPayloadCurr[1]));
 
 
+  // goto next stack
+  fPayloadCurr++;
+  fPayloadCurr++;
 
 
-TString AliTRDrawStream::EquipmentError(ErrorCode_t err, TString msg)
-{ 
-  // register error according to error code on equipment level 
+  return (fPayloadCurr-start);
+}
+
+Int_t AliTRDrawStream::SeekNextLink()
+{
+  // proceed in raw data stream till the next link
+
+  UInt_t *start = fPayloadCurr;
+
+  // read until data endmarkers
+  while (fPayloadCurr - fPayloadStart < fPayloadSize &&
+        ((fPayloadCurr[0] != fgkStackEndmarker[0]) ||
+         (fPayloadCurr[1] != fgkStackEndmarker[1])) &&
+        *fPayloadCurr != fgkDataEndmarker)
+    fPayloadCurr++;
+
+  // read all data endmarkers
+  while (fPayloadCurr - fPayloadStart < fPayloadSize &&
+        *fPayloadCurr == fgkDataEndmarker)
+    fPayloadCurr++;
+
+  return (fPayloadCurr - start);
+}
+
+
+void AliTRDrawStream::EquipmentError(ErrorCode_t err, const char *const msg, ...)
+{
+  // register error according to error code on equipment level
   // and return the corresponding error message
 
   // and return the corresponding error message
 
-  fLastError.fSector = fCurrEquipmentId - 1024;
+  fLastError.fSector = fCurrEquipmentId - kDDLOffset;
   fLastError.fStack  = -1;
   fLastError.fLink   = -1;
   fLastError.fRob    = -1;
   fLastError.fMcm    = -1;
   fLastError.fError  = err;
   fLastError.fStack  = -1;
   fLastError.fLink   = -1;
   fLastError.fRob    = -1;
   fLastError.fMcm    = -1;
   fLastError.fError  = err;
-  fErrors->Fill();
-
-  return (Form("Event %6i: Eq. %2d - %s : ", 
-              fRawReader->GetEventIndex(), fCurrEquipmentId, fgErrorMessages[err]) + msg); 
-}                                                                              
+  (this->*fStoreError)();
+
+  va_list ap;
+  if (fgErrorDebugLevel[err] > 10)
+    AliDebug(fgErrorDebugLevel[err],
+            Form("Event %6i: Eq. %2d - %s : %s",
+                 fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
+                 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
+  else
+    AliError(Form("Event %6i: Eq. %2d - %s : %s",
+                 fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
+                 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
+  fErrorFlags |= fgErrorBehav[err];
+}
 
 
 
 
-TString AliTRDrawStream::StackError(ErrorCode_t err, TString msg)
-{ 
-  // register error according to error code on stack level 
+void AliTRDrawStream::StackError(ErrorCode_t err, const char *const msg, ...)
+{
+  // register error according to error code on stack level
   // and return the corresponding error message
 
   // and return the corresponding error message
 
-  fLastError.fSector = fCurrEquipmentId - 1024;
+  fLastError.fSector = fCurrEquipmentId - kDDLOffset;
   fLastError.fStack  = fCurrSlot;
   fLastError.fLink   = -1;
   fLastError.fRob    = -1;
   fLastError.fMcm    = -1;
   fLastError.fError  = err;
   fLastError.fStack  = fCurrSlot;
   fLastError.fLink   = -1;
   fLastError.fRob    = -1;
   fLastError.fMcm    = -1;
   fLastError.fError  = err;
-  fErrors->Fill();
-
-  return (Form("Event %6i: Eq. %2d S %i - %s : ", 
-              fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgErrorMessages[err]) + msg); 
-} 
+  (this->*fStoreError)();
+
+  va_list ap;
+  if (fgErrorDebugLevel[err] > 0)
+    AliDebug(fgErrorDebugLevel[err],
+            Form("Event %6i: Eq. %2d S %i - %s : %s",
+                 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
+                 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
+  else
+    AliError(Form("Event %6i: Eq. %2d S %i - %s : %s",
+                 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
+                 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
+  fErrorFlags |= fgErrorBehav[err];
+}
 
 
 
 
-TString AliTRDrawStream::LinkError(ErrorCode_t err, TString msg)
-{ 
-  // register error according to error code on link level 
+void AliTRDrawStream::LinkError(ErrorCode_t err, const char *const msg, ...)
+{
+  // register error according to error code on link level
   // and return the corresponding error message
 
   // and return the corresponding error message
 
-  fLastError.fSector = fCurrEquipmentId - 1024;
+  fLastError.fSector = fCurrEquipmentId - kDDLOffset;
   fLastError.fStack  = fCurrSlot;
   fLastError.fLink   = fCurrLink;
   fLastError.fRob    = -1;
   fLastError.fMcm    = -1;
   fLastError.fError  = err;
   fLastError.fStack  = fCurrSlot;
   fLastError.fLink   = fCurrLink;
   fLastError.fRob    = -1;
   fLastError.fMcm    = -1;
   fLastError.fError  = err;
-  fErrors->Fill();
-
-  return (Form("Event %6i: Eq. %2d S %i l %2i - %s : ", 
-              fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgErrorMessages[err]) + msg); 
-} 
+  (this->*fStoreError)();
+
+  va_list ap;
+  if (fgErrorDebugLevel[err] > 0)
+    AliDebug(fgErrorDebugLevel[err],
+            Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
+                 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
+                 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
+  else
+    AliError(Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
+                 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
+                 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
+  fErrorFlags |= fgErrorBehav[err];
+}
 
 
 
 
-TString AliTRDrawStream::ROBError(ErrorCode_t err, TString msg)
-{ 
-  // register error according to error code on ROB level 
+void AliTRDrawStream::ROBError(ErrorCode_t err, const char *const msg, ...)
+{
+  // register error according to error code on ROB level
   // and return the corresponding error message
 
   // and return the corresponding error message
 
-  fLastError.fSector = fCurrEquipmentId - 1024;
+  fLastError.fSector = fCurrEquipmentId - kDDLOffset;
   fLastError.fStack  = fCurrSlot;
   fLastError.fLink   = fCurrLink;
   fLastError.fRob    = fCurrRobPos;
   fLastError.fMcm    = -1;
   fLastError.fError  = err;
   fLastError.fStack  = fCurrSlot;
   fLastError.fLink   = fCurrLink;
   fLastError.fRob    = fCurrRobPos;
   fLastError.fMcm    = -1;
   fLastError.fError  = err;
-  fErrors->Fill();
-
-  return (Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : ", 
-              fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgErrorMessages[err]) + msg); 
-} 
+  (this->*fStoreError)();
+
+  va_list ap;
+  if (fgErrorDebugLevel[err] > 0)
+    AliDebug(fgErrorDebugLevel[err],
+            Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
+                 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
+                 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
+  else
+    AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
+                 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
+                 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
+  fErrorFlags |= fgErrorBehav[err];
+}
 
 
 
 
-TString AliTRDrawStream::MCMError(ErrorCode_t err, TString msg)
-{ 
-  // register error according to error code on MCM level 
+void AliTRDrawStream::MCMError(ErrorCode_t err, const char *const msg, ...)
+{
+  // register error according to error code on MCM level
   // and return the corresponding error message
 
   // and return the corresponding error message
 
-  fLastError.fSector = fCurrEquipmentId - 1024;
+  fLastError.fSector = fCurrEquipmentId - kDDLOffset;
   fLastError.fStack  = fCurrSlot;
   fLastError.fLink   = fCurrLink;
   fLastError.fRob    = fCurrRobPos;
   fLastError.fMcm    = fCurrMcmPos;
   fLastError.fError  = err;
   fLastError.fStack  = fCurrSlot;
   fLastError.fLink   = fCurrLink;
   fLastError.fRob    = fCurrRobPos;
   fLastError.fMcm    = fCurrMcmPos;
   fLastError.fError  = err;
-  fErrors->Fill();
-
-  return (Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : ", 
-              fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgErrorMessages[err]) + msg); 
+  (this->*fStoreError)();
+
+  va_list ap;
+  if (fgErrorDebugLevel[err] > 0)
+    AliDebug(fgErrorDebugLevel[err],
+            Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
+                 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
+                 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
+  else
+    AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
+                 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
+                 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
+  fErrorFlags |= fgErrorBehav[err];
 }
 
 const char* AliTRDrawStream::GetErrorMessage(ErrorCode_t errCode)
 }
 
 const char* AliTRDrawStream::GetErrorMessage(ErrorCode_t errCode)
-{ 
+{
   // return the error message for the given error code
 
   // return the error message for the given error code
 
-  if (errCode > 0 && errCode < kLastErrorCode) 
-    return fgErrorMessages[errCode];
-  else 
-    return ""; 
-} 
+  if (errCode > 0 && errCode < kLastErrorCode)
+    return fgkErrorMessages[errCode];
+  else
+    return "";
+}
 
 void AliTRDrawStream::AliTRDrawStats::ClearStats()
 {
 
 void AliTRDrawStream::AliTRDrawStats::ClearStats()
 {
@@ -1227,11 +2266,11 @@ void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::AliTRDrawStatsHC::Cl
 }
 
 void AliTRDrawStream::SetDumpMCM(Int_t det, Int_t rob, Int_t mcm, Bool_t dump)
 }
 
 void AliTRDrawStream::SetDumpMCM(Int_t det, Int_t rob, Int_t mcm, Bool_t dump)
-{ 
+{
   // mark MCM for dumping of raw data
 
   if (dump) {
   // mark MCM for dumping of raw data
 
   if (dump) {
-    fDumpMCM[fNDumpMCMs++] = (det << 7) | (rob << 4) | mcm; 
+    fDumpMCM[fNDumpMCMs++] = (det << 7) | (rob << 4) | mcm;
   }
   else {
     Int_t iMCM;
   }
   else {
     Int_t iMCM;
@@ -1247,7 +2286,7 @@ void AliTRDrawStream::SetDumpMCM(Int_t det, Int_t rob, Int_t mcm, Bool_t dump)
   }
 }
 
   }
 }
 
-Bool_t AliTRDrawStream::DumpingMCM(Int_t det, Int_t rob, Int_t mcm) 
+Bool_t AliTRDrawStream::DumpingMCM(Int_t det, Int_t rob, Int_t mcm)  const
 {
   // check if MCM data should be dumped
 
 {
   // check if MCM data should be dumped
 
@@ -1259,18 +2298,176 @@ Bool_t AliTRDrawStream::DumpingMCM(Int_t det, Int_t rob, Int_t mcm)
   return kFALSE;
 }
 
   return kFALSE;
 }
 
-void AliTRDrawStream::DumpRaw(TString title, UInt_t *start, Int_t length)
+TString AliTRDrawStream::DumpRaw(TString title, const UInt_t *start, Int_t length, UInt_t endmarker)
 {
   // dump raw data
 
   title += "\n";
 {
   // dump raw data
 
   title += "\n";
-  Int_t pos = 0;
-  for ( ; pos+3 < length; pos += 4) {
-    title += Form("0x%08x 0x%08x 0x%08x 0x%08x\n", 
-                 start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
+  for (Int_t pos = 0; pos < length; pos += 4) {
+    if ((start[pos+0] != endmarker) && pos+0 < length)
+      if ((start[pos+1] != endmarker && pos+1 < length))
+       if ((start[pos+2] != endmarker && pos+2 < length))
+         if ((start[pos+3] != endmarker && pos+3 < length))
+           title += Form("   0x%08x 0x%08x 0x%08x 0x%08x\n",
+                         start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
+         else {
+           title += Form("   0x%08x 0x%08x 0x%08x 0x%08x\n",
+                         start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
+           return title;
+         }
+       else {
+         title += Form("   0x%08x 0x%08x 0x%08x\n",
+                       start[pos+0], start[pos+1], start[pos+2]);
+         return title;
+       }
+      else {
+       title += Form("   0x%08x 0x%08x\n",
+                     start[pos+0], start[pos+1]);
+       return title;
+      }
+    else {
+      title += Form("   0x%08x\n",
+                   start[pos+0]);
+      return title;
+    }
   }
   }
-  for ( ; pos < length; pos++) {
-    title += Form("0x%08x ", start[pos]);
+  return title;
+}
+
+TString AliTRDrawStream::DumpMcmHeader(TString title, UInt_t word)
+{
+  title += Form("0x%08x -> ROB: %i, MCM: %2i",
+               word, ROB(word), MCM(word));
+  return title;
+}
+
+TString AliTRDrawStream::DumpAdcMask(TString title, UInt_t word)
+{
+  title += Form("0x%08x -> #ch : %2i, 0x%06x (%2i ch)",
+               word, GetNActiveChannels(word), GetActiveChannels(word), GetNActiveChannelsFromMask(word));
+  return title;
+}
+
+AliTRDrawStream::AliTRDrawStreamError::AliTRDrawStreamError(Int_t error, Int_t sector, Int_t stack, Int_t link, Int_t rob, Int_t mcm) :
+  fError(error),
+  fSector(sector),
+  fStack(stack),
+  fLink(link),
+  fRob(rob),
+  fMcm(mcm)
+{
+  // ctor
+
+}
+
+void AliTRDrawStream::SortTracklets(TClonesArray *trklArray, TList &sortedTracklets, Int_t *indices)
+{
+  // sort tracklets for referencing from GTU tracks
+
+  if (!trklArray)
+    return;
+
+  Int_t nTracklets = trklArray->GetEntriesFast();
+
+  Int_t lastHC = -1;
+  for (Int_t iTracklet = 0; iTracklet < nTracklets; iTracklet++) {
+    AliTRDtrackletBase *trkl = (AliTRDtrackletBase*) ((*trklArray)[iTracklet]);
+    Int_t hc = trkl->GetHCId();
+    if ((hc < 0) || (hc >= 1080)) {
+      AliErrorClass(Form("HC for tracklet: 0x%08x out of range: %i", trkl->GetTrackletWord(), trkl->GetHCId()));
+      continue;
+    }
+    AliDebugClass(5, Form("hc: %4i : 0x%08x z: %2i", hc, trkl->GetTrackletWord(), trkl->GetZbin()));
+    if (hc != lastHC) {
+      AliDebugClass(2, Form("set tracklet index for HC %i to %i", hc, iTracklet));
+      indices[hc] = iTracklet + 1;
+      lastHC = hc;
+    }
+  }
+
+  for (Int_t iDet = 0; iDet < 540; iDet++) {
+    Int_t trklIndexA = indices[2*iDet + 0] - 1;
+    Int_t trklIndexB = indices[2*iDet + 1] - 1;
+    Int_t trklIndex  = sortedTracklets.GetEntries();
+    AliTRDtrackletBase *trklA = trklIndexA > -1 ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
+    AliTRDtrackletBase *trklB = trklIndexB > -1 ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
+    AliTRDtrackletBase *trklNext = 0x0;
+    while (trklA != 0x0 || trklB != 0x0) {
+      AliDebugClass(5, Form("det %i - A: %i/%i -> %p, B: %i/%i -> %p",
+                      iDet, trklIndexA, nTracklets, trklA, trklIndexB, nTracklets, trklB));
+      if (trklA == 0x0) {
+       trklNext = trklB;
+       trklIndexB++;
+       trklB = trklIndexB < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
+       if (trklB && trklB->GetHCId() != 2*iDet + 1)
+         trklB = 0x0;
+      }
+      else if (trklB == 0x0) {
+       trklNext = trklA;
+       trklIndexA++;
+       trklA = trklIndexA < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
+       if (trklA && trklA->GetHCId() != 2*iDet)
+         trklA = 0x0;
+      }
+      else {
+       if (trklA->GetZbin() <= trklB->GetZbin()) {
+         trklNext = trklA;
+         trklIndexA++;
+         trklA = trklIndexA < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexA]) : 0x0;
+         if (trklA && trklA->GetHCId() != 2*iDet)
+           trklA = 0x0;
+       }
+       else {
+         trklNext = trklB;
+         trklIndexB++;
+         trklB = trklIndexB < nTracklets ? (AliTRDtrackletBase*) ((*trklArray)[trklIndexB]) : 0x0;
+         if (trklB && trklB->GetHCId() != 2*iDet + 1)
+           trklB = 0x0;
+       }
+      }
+      if (trklNext) {
+       sortedTracklets.Add(trklNext);
+
+      }
+    }
+
+    // updating tracklet indices as in output
+    if (sortedTracklets.GetEntries() != trklIndex) {
+      indices[2*iDet + 0] = trklIndex;
+      indices[2*iDet + 1] = sortedTracklets.GetEntries();
+    } else {
+      indices[2*iDet + 0] = indices[2*iDet + 1] = -1;
+    }
+  }
+}
+
+void AliTRDrawStream::AssignTracklets(AliESDTrdTrack *trdTrack, Int_t *trackletIndex, Int_t refIndex[6])
+{
+  UInt_t mask  = trdTrack->GetLayerMask();
+  UInt_t stack = trdTrack->GetStack();
+
+  for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
+    refIndex[iLayer] = -1;
+
+    if (mask & (1 << iLayer)) {
+
+      Int_t det = trdTrack->GetSector()*30 + stack*6 + iLayer;
+      Int_t idx = trdTrack->GetTrackletIndex(iLayer);
+
+      if ((det < 0) || (det > 539)) {
+       AliErrorClass(Form("Invalid detector no. from track: %i", 2*det));
+       continue;
+      }
+      if (trackletIndex[2*det] >= 0) {
+       if ((trackletIndex[2*det] + idx > -1) &&
+           (trackletIndex[2*det] + idx < trackletIndex[2*det+1])) {
+         refIndex[iLayer] = trackletIndex[2*det] + idx;
+       } else {
+         AliErrorClass(Form("Requested tracklet index %i out of range", idx));
+       }
+      } else {
+       AliErrorClass(Form("Non-existing tracklets requested in det %i", det));
+      }
+    }
   }
   }
-  AliInfo(title);
 }
 }