]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - TRD/AliTRDrawStream.cxx
Bug fix (Xianguo)
[u/mrichter/AliRoot.git] / TRD / AliTRDrawStream.cxx
index c12d8d9b572b9fe1684e14d2f08c2da329fb33b0..ea312fcde9c6a86351eac91cf284aa220392a110 100644 (file)
@@ -16,7 +16,7 @@
 ////////////////////////////////////////////////////////////////////////////
 //                                                                        //
 //  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         //
 //                                                                        //
 //  Author: J. Klein (jochen.klein@cern.ch)                               //
 //                                                                        //
 //                                                                        //
 //  Author: J. Klein (jochen.klein@cern.ch)                               //
 //                                                                        //
 #include "AliRawReader.h"
 #include "AliTRDdigitsManager.h"
 #include "AliTRDdigitsParam.h"
 #include "AliRawReader.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 "AliTRDtrackletMCM.h"
 #include "AliESDTrdTrack.h"
 #include "AliTreeLoader.h"
 #include "AliESDTrdTrack.h"
 #include "AliTreeLoader.h"
+#include "AliLoader.h"
 
 #include "AliTRDrawStream.h"
 
 
 #include "AliTRDrawStream.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::fgkErrorMessages[] = {
   "Unknown error",
   "Link monitor active",
 
 const char* AliTRDrawStream::fgkErrorMessages[] = {
   "Unknown error",
   "Link monitor active",
-  "Pretrigger counter mismatch",
+  "Event counter mismatch",
   "not a TRD equipment (1024-1041)",
   "Invalid Stack header",
   "Invalid detector number",
   "No digits could be retrieved from the digitsmanager",
   "not a TRD equipment (1024-1041)",
   "Invalid Stack header",
   "Invalid detector number",
   "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,
 };
 
 Int_t AliTRDrawStream::fgErrorDebugLevel[] = {
   0,
   0,
-  2, 
-  1, 
-  0, 
-  1, 
-  1, 
+  2,
+  1,
+  0,
+  1,
+  1,
+  1,
   1,
   1,
-  1, 
   2,
   1,
   2,
   1,
+  0,
   1,
   1,
   1,
   1,
-  1, 
-  2, 
-  1, 
-  1, 
-  1
+  2,
+  1,
+  1,
+  1,
+  0,
+  0
 };
 
 AliTRDrawStream::ErrorBehav_t AliTRDrawStream::fgErrorBehav[] = {
 };
 
 AliTRDrawStream::ErrorBehav_t AliTRDrawStream::fgErrorBehav[] = {
@@ -118,11 +129,12 @@ AliTRDrawStream::ErrorBehav_t AliTRDrawStream::fgErrorBehav[] = {
   AliTRDrawStream::kTolerate,
   AliTRDrawStream::kTolerate,
   AliTRDrawStream::kTolerate,
   AliTRDrawStream::kTolerate,
   AliTRDrawStream::kTolerate,
   AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kTolerate,
+  AliTRDrawStream::kTolerate,
   AliTRDrawStream::kTolerate
 };
 
 AliTRDrawStream::AliTRDrawStream(AliRawReader *rawReader) :
   AliTRDrawStream::kTolerate
 };
 
 AliTRDrawStream::AliTRDrawStream(AliRawReader *rawReader) :
-  fStats(), 
   fStoreError(&AliTRDrawStream::ForgetError),
   fRawReader(rawReader),
   fDigitsManager(0x0),
   fStoreError(&AliTRDrawStream::ForgetError),
   fRawReader(rawReader),
   fDigitsManager(0x0),
@@ -130,6 +142,7 @@ AliTRDrawStream::AliTRDrawStream(AliRawReader *rawReader) :
   fErrors(0x0),
   fLastError(),
   fErrorFlags(0),
   fErrors(0x0),
   fLastError(),
   fErrorFlags(0),
+  fStats(),
   fPayloadStart(0x0),
   fPayloadCurr(0x0),
   fPayloadSize(0),
   fPayloadStart(0x0),
   fPayloadCurr(0x0),
   fPayloadSize(0),
@@ -140,21 +153,40 @@ 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),
+  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(0),
+  fCurrMatchFlagsPostBP(0),
+  fCurrChecksumStack(),
+  fCurrChecksumSIU(0),
   fCurrSpecial(-1),
   fCurrMajor(-1),
   fCurrMinor(-1),
   fCurrSpecial(-1),
   fCurrMajor(-1),
   fCurrMinor(-1),
@@ -180,16 +212,24 @@ AliTRDrawStream::AliTRDrawStream(AliRawReader *rawReader) :
 {
   // 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];
+  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];             
+  fCurrLinkMask           = new UInt_t[fgkNstacks];
+  fCurrCleanCheckout      = new UInt_t[fgkNstacks];
+  fCurrBoardId            = new UInt_t[fgkNstacks];
+  fCurrHwRevTMU           = new UInt_t[fgkNstacks];
   fCurrLinkMonitorFlags   = new UInt_t[fgkNstacks * fgkNlinks];
   fCurrLinkDataTypeFlags  = new UInt_t[fgkNstacks * fgkNlinks];
   fCurrLinkDebugFlags     = new UInt_t[fgkNstacks * fgkNlinks];
   fCurrLinkMonitorFlags   = new UInt_t[fgkNstacks * fgkNlinks];
   fCurrLinkDataTypeFlags  = new UInt_t[fgkNstacks * fgkNlinks];
   fCurrLinkDebugFlags     = new UInt_t[fgkNstacks * fgkNlinks];
+  for (Int_t iSector = 0; iSector < fgkNsectors; iSector++)
+    fCurrTrgFlags[iSector] = 0;
   for (Int_t i = 0; i < 100; i++)
     fDumpMCM[i] = 0;
 
   for (Int_t i = 0; i < 100; i++)
     fDumpMCM[i] = 0;
 
@@ -213,13 +253,19 @@ 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;
@@ -241,7 +287,7 @@ Bool_t AliTRDrawStream::ReadEvent(TTree *trackletTree)
   fDigitsParam = 0x0;
 
   // loop over all DDLs
   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)) {
@@ -249,54 +295,57 @@ 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) {
+    if (fCurrEquipmentId < kDDLOffset || fCurrEquipmentId > kDDLMax) {
       EquipmentError(kNonTrdEq, "Skipping");
       continue;
     }
 
       EquipmentError(kNonTrdEq, "Skipping");
       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);
 
 
-    // read stack index header
-    for (Int_t iStack = 0; iStack < 5; iStack++) {
-      if ((fCurrStackMask & (1 << iStack)) != 0) 
-       ReadStackIndexHeader(iStack);
-    }
+    if (fCurrTrailerReadout)
+      ReadGTUTrailer();
 
 
-    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) 
+      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   = (fCurrEquipmentId - 1024) * 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;
-       
+
+       Int_t   size  = 0;
+
        fErrorFlags = 0;
        // check for link monitor error flag
        fErrorFlags = 0;
        // check for link monitor error flag
-       if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0)
+       if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0) {
          LinkError(kLinkMonitor);
          LinkError(kLinkMonitor);
-
-       // read the data from one HC
-       ReadLinkData();
+         if (fgErrorBehav[kLinkMonitor] == kTolerate)
+           size += ReadLinkData();
+       }
+       else
+         // read the data from one HC
+         size += ReadLinkData();
 
        // read all data endmarkers
 
        // read all data endmarkers
-       SeekNextLink();
+       size += SeekNextLink();
       }
       }
+
+      // continue with next stack
+      SeekNextStack();
     }
   }
     }
   }
+
   return kTRUE;
 }
 
   return kTRUE;
 }
 
@@ -318,29 +367,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) {
+
+    if (fCurrEquipmentId < kDDLOffset || fCurrEquipmentId > kDDLMax) {
       EquipmentError(kNonTrdEq, "Skipping");
       continue;
     }
 
       EquipmentError(kNonTrdEq, "Skipping");
       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;
   }
 
@@ -348,13 +389,13 @@ 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;
 
   fErrorFlags = 0;
   fDigitsParam   = 0x0;
 
   fErrorFlags = 0;
@@ -366,9 +407,9 @@ Int_t AliTRDrawStream::NextChamber(AliTRDdigitsManager *digMgr, UInt_t ** /* tra
   AliDataLoader *trklLoader = trdLoader ? trdLoader->GetDataLoader("tracklets") : NULL;
   if (trklLoader) {
     AliTreeLoader *trklTreeLoader = (AliTreeLoader*) trklLoader->GetBaseLoader("tracklets-raw");
   AliDataLoader *trklLoader = trdLoader ? trdLoader->GetDataLoader("tracklets") : NULL;
   if (trklLoader) {
     AliTreeLoader *trklTreeLoader = (AliTreeLoader*) trklLoader->GetBaseLoader("tracklets-raw");
-    if (trklTreeLoader) 
+    if (trklTreeLoader)
       trklTree = trklTreeLoader->Tree();
       trklTree = trklTreeLoader->Tree();
-    else 
+    else
       trklTree = trklLoader->Tree();
   }
 
       trklTree = trklLoader->Tree();
   }
 
@@ -380,16 +421,16 @@ Int_t AliTRDrawStream::NextChamber(AliTRDdigitsManager *digMgr, UInt_t ** /* tra
     return -1;
   }
 
     return -1;
   }
 
-  while (fCurrSlot < 0 || fCurrSlot >= 5) {
+  while (fCurrSlot < 0 || fCurrSlot >= fgkNstacks) {
     if (!NextDDL()) {
       fCurrSlot = -1;
       return -1;
     }
     if (!NextDDL()) {
       fCurrSlot = -1;
       return -1;
     }
-    while ((fCurrSlot < 5) &&
+    while ((fCurrSlot < fgkNstacks) &&
           (((fCurrStackMask & (1 << fCurrSlot)) == 0) ||
            ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0)) {
       fCurrLink++;
           (((fCurrStackMask & (1 << fCurrSlot)) == 0) ||
            ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0)) {
       fCurrLink++;
-      if (fCurrLink > 11) {
+      if (fCurrLink >= fgkNlinks) {
        fCurrLink = 0;
        fCurrSlot++;
       }
        fCurrLink = 0;
        fCurrSlot++;
       }
@@ -397,14 +438,18 @@ Int_t AliTRDrawStream::NextChamber(AliTRDdigitsManager *digMgr, UInt_t ** /* tra
   }
 
   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[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
   SeekNextLink();
 
   // read all data endmarkers
   SeekNextLink();
 
@@ -413,34 +458,92 @@ Int_t AliTRDrawStream::NextChamber(AliTRDdigitsManager *digMgr, UInt_t ** /* tra
     fCurrLink++;
     fCurrHC++;
     if (fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) {
     fCurrLink++;
     fCurrHC++;
     if (fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) {
-      ReadLinkData();
+      if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0) {
+       LinkError(kLinkMonitor);
+       if (fgErrorBehav[kLinkMonitor] == kTolerate)
+         ReadLinkData();
+      }
+      else {
+       ReadLinkData();
+      }
       SeekNextLink();
     }
   }
 
       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));
 
   // return chamber information from HC if it is valid
   // otherwise return information from link position
            ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0));
 
   // return chamber information from HC if it is valid
   // otherwise return information from link position
-  if (fCurrSm < 0 || fCurrSm > 17 || fCurrStack < 0 || fCurrStack > 4 || fCurrLayer < 0 || fCurrLayer > 5)
-    return ((fCurrEquipmentId-1024) + fCurrSlot * 6 + fCurrLink/2);
+  if (fCurrSm < 0 || fCurrSm >= fgkNsectors || fCurrStack < 0 || fCurrStack >= fgkNstacks || fCurrLayer < 0 || fCurrLayer >= fgkNlinks/2)
+    return ((fCurrEquipmentId-kDDLOffset) + fCurrSlot * fgkNlinks/2 + fCurrLink/2);
   else
   else
-    return (fCurrSm * 30 + fCurrStack * 6 + fCurrLayer);
+    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) {
@@ -448,57 +551,536 @@ Int_t AliTRDrawStream::ReadSmHeader()
     return -1;
   }
 
     return -1;
   }
 
-  fCurrSmuIndexHeaderSize     = ((*fPayloadCurr) >> 16) & 0xffff;
-  fCurrSmuIndexHeaderVersion  = ((*fPayloadCurr) >> 12) &    0xf;
-  //  fCurrSmuIndexHeaderTrgAvail = ((*fPayloadCurr) >>  9) &    0x1;
-  //  fCurrSmuIndexHeaderEvType   = ((*fPayloadCurr) >>  7) &    0x3;
+  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;
+    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));
+                  fCurrStackMask,
+                  fCurrTrailerReadout,
+                  fCurrTrgHeaderAvail,
+                  fCurrTrkHeaderAvail ));
+
+  // jump to the first word after the SM header
+  fPayloadCurr += fCurrSmHeaderSize + 1;
+
+  return fCurrSmHeaderSize + 1;
+}
 
 
+Int_t AliTRDrawStream::DecodeGTUtracks()
+{
   // decode GTU track words
   // decode GTU track words
-  UInt_t trackWord[2] = { 0, 0 };
-  Int_t stack = 0;
+  // 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 idx = 0;
-  for (UInt_t iWord = 4; iWord < fCurrSmuIndexHeaderSize; iWord++) {
-    if (fPayloadCurr[iWord] == 0x10000000) {
-      stack++;
-      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 {
     }
     else {
-      if ((idx == 0) &&
-         ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
-       AliDebug(1,Form("stack %i: fast trigger word: 0x%08x", stack, fPayloadCurr[iWord]));
-       continue;
-      }
-      else if ((idx & 0x1)==0x1) {
-       trackWord[idx&0x1] = fPayloadCurr[iWord];
-       AliDebug(1,Form("track debug word: 0x%08x%08x", trackWord[1], trackWord[0]));
-//     if (fTracks)
-//       new ((*fTracks)[fTracks->GetEntriesFast()]) AliESDTrdTrack(0, 0, trackWord[0], trackWord[1], fCurrEquipmentId-1024);
+      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 {
       }
       else {
-       trackWord[idx&0x1] = fPayloadCurr[iWord];
+       // 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->SetReserved((trackWord >> 49) & 0x7);
+         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 (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++;
     }
     }
+    idx++;
   }
 
   }
 
-  fPayloadCurr += fCurrSmuIndexHeaderSize + 1;
+  fPayloadCurr += fCurrTrkHeaderSize[stack];
 
 
-  return fCurrSmuIndexHeaderSize + 1;
+  return fCurrTrkHeaderSize[stack];
 }
 
 }
 
-Int_t AliTRDrawStream::ReadStackIndexHeader(Int_t stack)
+Int_t AliTRDrawStream::ReadTriggerHeaders()
 {
 {
-  // read the stack index header 
+  // 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;
@@ -506,22 +1088,28 @@ 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]) {
-    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:
     if (fCurrStackHeaderSize[stack] < 8) {
     if (fCurrStackHeaderSize[stack] < 8) {
-      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
       fCurrLinkMonitorFlags  [stack*fgkNlinks + iLayer*2]      = fPayloadCurr[iLayer+2] & 0xf;
     for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
       // A side
       fCurrLinkMonitorFlags  [stack*fgkNlinks + iLayer*2]      = fPayloadCurr[iLayer+2] & 0xf;
@@ -533,16 +1121,63 @@ Int_t AliTRDrawStream::ReadStackIndexHeader(Int_t stack)
       fCurrLinkDebugFlags    [stack*fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 28) & 0xf;
     }
     break;
       fCurrLinkDebugFlags    [stack*fgkNlinks + iLayer*2 + 1]  = (fPayloadCurr[iLayer+2] >> 28) & 0xf;
     }
     break;
-    
+
   default:
   default:
-    StackError(kStackHeaderInvalid, "Invalid Stack Index Header version %x", fCurrStackHeaderVersion[stack]);
+    LinkError(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; iWord++) {
+    if ((fPayloadStart[fPayloadSize-1-iWord] & 0xffff) == 0x1f51) {
+      trailer = fPayloadStart + fPayloadSize - 1 - iWord;
+      break;
+    }
+  }
+
+  if (((*trailer) & 0xffff) == 0x1f51) {
+    UInt_t trailerIndexWord = (*trailer);
+    Int_t trailerSize = (trailerIndexWord >> 16) & 0xffff;
+    AliDebug(2, DumpRaw("GTU trailer", trailer, trailerSize+1));
+    // parse the trailer
+    if (trailerSize >= 4) {
+      // match flags from GTU
+      fCurrMatchFlagsSRAM     = (trailer[1] >>  0) &    0x1f;
+      fCurrMatchFlagsPostBP   = (trailer[1] >>  5) &    0x1f;
+      // individual checksums
+      fCurrChecksumStack[0]   = (trailer[1] >> 16) &  0xffff;
+      fCurrChecksumStack[1]   = (trailer[2] >>  0) &  0xffff;
+      fCurrChecksumStack[2]   = (trailer[2] >> 16) &  0xffff;
+      fCurrChecksumStack[3]   = (trailer[3] >>  0) &  0xffff;
+      fCurrChecksumStack[4]   = (trailer[3] >> 16) &  0xffff;
+      fCurrChecksumSIU        = trailer[4];
+
+      if ((fCurrMatchFlagsSRAM & fCurrStackMask) != fCurrStackMask)
+       EquipmentError(kCRCmismatch, "CRC mismatch SRAM: 0x%02x", fCurrMatchFlagsSRAM);
+      if ((fCurrMatchFlagsPostBP & fCurrStackMask) != fCurrStackMask)
+       EquipmentError(kCRCmismatch, "CRC mismatch BP: 0x%02x", fCurrMatchFlagsPostBP);
+
+    }
+    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
@@ -551,23 +1186,23 @@ 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()])
 
   if (fMarkers)
     new ((*fMarkers)[fMarkers->GetEntriesFast()])
-      AliTRDrawStreamError(-kHCactive, fCurrSm, fCurrStack, fCurrLink);
+      AliTRDrawStreamError(-kHCactive, fCurrEquipmentId-kDDLOffset, fCurrSlot, fCurrLink);
 
   if (fErrorFlags & kDiscardHC)
     return count;
 
 
   if (fErrorFlags & kDiscardHC)
     return count;
 
-  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();
   if (fErrorFlags & kDiscardHC)
     return count;
   count += ReadHcHeader();
   if (fErrorFlags & kDiscardHC)
     return count;
@@ -575,40 +1210,7 @@ Int_t AliTRDrawStream::ReadLinkData()
   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 {
-      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) {
@@ -618,24 +1220,68 @@ 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 {
@@ -662,17 +1308,16 @@ Int_t AliTRDrawStream::ReadTracklets()
   fTrackletArray->Clear();
 
   UInt_t *start = fPayloadCurr;
   fTrackletArray->Clear();
 
   UInt_t *start = fPayloadCurr;
-  while (*(fPayloadCurr) != fgkTrackletEndmarker && 
+  while (*(fPayloadCurr) != fgkTrackletEndmarker &&
         fPayloadCurr - fPayloadStart < fPayloadSize) {
         fPayloadCurr - fPayloadStart < fPayloadSize) {
-
     new ((*fTrackletArray)[fTrackletArray->GetEntriesFast()]) AliTRDtrackletWord(*(fPayloadCurr), fCurrHC);
 
     fPayloadCurr++;
   }
 
   if (fTrackletArray->GetEntriesFast() > 0) {
     new ((*fTrackletArray)[fTrackletArray->GetEntriesFast()]) AliTRDtrackletWord(*(fPayloadCurr), fCurrHC);
 
     fPayloadCurr++;
   }
 
   if (fTrackletArray->GetEntriesFast() > 0) {
-    AliDebug(1, Form("Found %i tracklets in %i %i %i (ev. %i)", fTrackletArray->GetEntriesFast(), 
-                    (fCurrEquipmentId-1024), fCurrSlot, fCurrLink, fRawReader->GetEventIndex()));
+    AliDebug(1, Form("Found %i tracklets in %i %i %i (ev. %i)", fTrackletArray->GetEntriesFast(),
+                    (fCurrEquipmentId-kDDLOffset), fCurrSlot, fCurrLink, fRawReader->GetEventIndex()));
     if (fCurrSm > -1 && fCurrSm < 18) {
       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNTracklets += fTrackletArray->GetEntriesFast();
       fStats.fStatsSector[fCurrSm].fNTracklets                      += fTrackletArray->GetEntriesFast();
     if (fCurrSm > -1 && fCurrSm < 18) {
       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNTracklets += fTrackletArray->GetEntriesFast();
       fStats.fStatsSector[fCurrSm].fNTracklets                      += fTrackletArray->GetEntriesFast();
@@ -686,10 +1331,10 @@ Int_t AliTRDrawStream::ReadTracklets()
   }
 
   // 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;
 }
 
@@ -698,6 +1343,7 @@ 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
   if (*fPayloadCurr == fgkDataEndmarker)
   UInt_t *start = fPayloadCurr;
   // check not to be at the data endmarker
   if (*fPayloadCurr == fgkDataEndmarker)
@@ -713,28 +1359,28 @@ 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) {
+  if ((fCurrSm != (((Int_t) fCurrEquipmentId) - kDDLOffset)) ||
+      (fCurrStack != fCurrSlot) ||
+      (fCurrLayer != fCurrLink / 2) ||
+      (fCurrSide != fCurrLink % 2)) {
     LinkError(kHCmismatch,
     LinkError(kHCmismatch,
-             "HC: %i, %i, %i, %i\n 0x%08x 0x%08x 0x%08x 0x%08x", 
+             "HC: %i, %i, %i, %i\n 0x%08x 0x%08x 0x%08x 0x%08x",
              fCurrSm, fCurrStack, fCurrLayer, fCurrSide,
              fCurrSm, fCurrStack, fCurrLayer, fCurrSide,
-             fPayloadCurr[0], fPayloadCurr[1], fPayloadCurr[2], fPayloadCurr[3]);;
+             fPayloadCurr[0], fPayloadCurr[1], fPayloadCurr[2], fPayloadCurr[3]);
   }
   if (fCurrCheck != 0x1) {
     LinkError(kHCcheckFailed);
   }
   }
   if (fCurrCheck != 0x1) {
     LinkError(kHCcheckFailed);
   }
-  
+
   if (fCurrAddHcWords > 0) {
     fCurrNtimebins = (fPayloadCurr[1] >> 26) & 0x3f;
     fCurrBC = (fPayloadCurr[1] >> 10) & 0xffff;
     fCurrPtrgCnt = (fPayloadCurr[1] >> 6) & 0xf;
     fCurrPtrgPhase = (fPayloadCurr[1] >> 2) & 0xf;
   }
   if (fCurrAddHcWords > 0) {
     fCurrNtimebins = (fPayloadCurr[1] >> 26) & 0x3f;
     fCurrBC = (fPayloadCurr[1] >> 10) & 0xffff;
     fCurrPtrgCnt = (fPayloadCurr[1] >> 6) & 0xf;
     fCurrPtrgPhase = (fPayloadCurr[1] >> 2) & 0xf;
   }
-  
+
   fPayloadCurr += 1 + fCurrAddHcWords;
   fPayloadCurr += 1 + fCurrAddHcWords;
-  
+
   return (fPayloadCurr - start);
 }
 
   return (fPayloadCurr - start);
 }
 
@@ -744,6 +1390,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;
@@ -757,34 +1404,45 @@ 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 {
-      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 {
-      MCMError(kPosUnexp);
+      MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
+    }
+
+    if (EvNo(*fPayloadCurr) != evno) {
+      if (evno == -1) {
+       evno = EvNo(*fPayloadCurr);
+      }
+      else {
+       MCMError(kEvCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
+      }
     }
     }
-    fCurrMcmPos = MCM(*fPayloadCurr);
-    
 
     fPayloadCurr++;
 
     fPayloadCurr++;
-    
+
     evcnt = 0x3f & *fPayloadCurr >> 26;
     cpu = -1;
     channelcount = 0;
     evcnt = 0x3f & *fPayloadCurr >> 26;
     cpu = -1;
     channelcount = 0;
@@ -795,13 +1453,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;
@@ -813,14 +1476,14 @@ 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;
@@ -828,29 +1491,43 @@ Int_t AliTRDrawStream::ReadTPData(Int_t mode)
        }
 
        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) {
          MCMError(kTPmismatch,
        if (diff != 0) {
          MCMError(kTPmismatch,
-                  "Seen 0x%08x, expected 0x%08x, diff: 0x%08x (0x%02x)", 
-                  *fPayloadCurr, expword, diff, 0xff & (diff | diff >> 8 | diff >> 16 | diff >> 24));;
+                  "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;
@@ -864,61 +1541,69 @@ Int_t AliTRDrawStream::ReadZSData()
   Int_t lastrobpos = -1;
 
   if (fCurrNtimebins != fNtimebins) {
   Int_t lastrobpos = -1;
 
   if (fCurrNtimebins != fNtimebins) {
-    if (fNtimebins > 0) 
+    if (fNtimebins > 0)
       LinkError(kNtimebinsChanged,
                "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
     fNtimebins = fCurrNtimebins;
   }
       LinkError(kNtimebinsChanged,
                "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
     fNtimebins = fCurrNtimebins;
   }
-  
+
   timebins = fNtimebins;
   timebins = fNtimebins;
-  
-  while (*(fPayloadCurr) != fgkDataEndmarker && 
+
+  while (*(fPayloadCurr) != fgkDataEndmarker &&
         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 {
-      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 {
-      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)
        evno = EvNo(*fPayloadCurr);
       else {
     if (EvNo(*fPayloadCurr) != evno) {
       if (evno == -1)
        evno = EvNo(*fPayloadCurr);
       else {
-       MCMError(kPtrgCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
+       MCMError(kEvCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
       }
     }
     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(kUnknown, "Data in padrow > 11 for stack 2");
+    }
+
     // ----- 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) {
@@ -926,89 +1611,90 @@ 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) {
        MCMError(kAdcMaskInconsistent,
             fPayloadCurr - fPayloadStart < fPayloadSize - 10 * channelcountExp - 1) {
        MCMError(kAdcMaskInconsistent,
-                "Possible MCM-H: 0x%08x, possible ADC-mask: 0x%08x", 
-                *(fPayloadCurr + 10 * channelcountExp), 
+                "Possible MCM-H: 0x%08x, possible ADC-mask: 0x%08x",
+                *(fPayloadCurr + 10 * channelcountExp),
                 *(fPayloadCurr + 10 * channelcountExp + 1) );
                 *(fPayloadCurr + 10 * channelcountExp + 1) );
-       if (!CouldBeMCMhdr( *(fPayloadCurr + 10 * channelcountExp)) && !CouldBeADCmask( *(fPayloadCurr + 10 * channelcountExp + 1))) 
+       if (!CouldBeMCMhdr( *(fPayloadCurr + 10 * channelcountExp)) && !CouldBeADCmask( *(fPayloadCurr + 10 * channelcountExp + 1)))
          channelcountExp++;
        else {
          break;
        }
       }
       MCMError(kAdcMaskInconsistent,
          channelcountExp++;
        else {
          break;
        }
       }
       MCMError(kAdcMaskInconsistent,
-              "Inconsistency in no. of active channels: Counter: %i, Mask: %i, chosen: %i!", 
+              "Inconsistency in no. of active channels: Counter: %i, Mask: %i, chosen: %i!",
               GetNActiveChannels(fPayloadCurr[-1]), GetNActiveChannelsFromMask(fPayloadCurr[-1]), channelcountExp);
     }
               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) {
       if (channelno < 20)
        channelno++;
       while (channelno < 20 && (channelmask & 1 << channelno) == 0)
        channelno++;
     // ----- reading marked ADC channels -----
     while (channelcount < channelcountExp && *(fPayloadCurr) != fgkDataEndmarker) {
       if (channelno < 20)
        channelno++;
       while (channelno < 20 && (channelmask & 1 << channelno) == 0)
        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) {
            MCMError(kAdcCheckInvalid,
        int check = 0x3 & *fPayloadCurr;
        if (channelno % 2 != 0) { // odd channel
          if (check != 0x2 && channelno < 21) {
            MCMError(kAdcCheckInvalid,
-                    "%i for %2i. ADC word in odd channel %i", 
+                    "%i for %2i. ADC word in odd channel %i",
                     check, adcwc+1, channelno);
          }
        }
        else {                  // even channel
          if (check != 0x3 && channelno < 21) {
            MCMError(kAdcCheckInvalid,
                     check, adcwc+1, channelno);
          }
        }
        else {                  // even channel
          if (check != 0x3 && channelno < 21) {
            MCMError(kAdcCheckInvalid,
-                    "%i for %2i. ADC word in even channel %i", 
+                    "%i for %2i. ADC word in even channel %i",
                     check, adcwc+1, channelno);
          }
        }
                     check, adcwc+1, channelno);
          }
        }
-       
+
        // filling the actual timebin data
        int tb2 = 0x3ff & *fPayloadCurr >> 22;
        int tb1 = 0x3ff & *fPayloadCurr >> 12;
        int tb0 = 0x3ff & *fPayloadCurr >> 2;
        // 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) 
+       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);
          fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
        else
          tb0 = -1;
        fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
        fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
-       
+
        adcwc++;
        fPayloadCurr++;
       }
        adcwc++;
        fPayloadCurr++;
       }
-      
-      if (adcwc != timebins / 3) 
+
+      if (adcwc != nADCwords)
        MCMError(kAdcDataAbort);
        MCMError(kAdcDataAbort);
-      
-      // adding index 
+
+      // adding index
       if (padcol > 0 && padcol < 144) {
        fSignalIndex->AddIndexRC(row, padcol);
       }
       if (padcol > 0 && padcol < 144) {
        fSignalIndex->AddIndexRC(row, padcol);
       }
-      
+
       channelcount++;
     }
 
       channelcount++;
     }
 
@@ -1018,7 +1704,7 @@ Int_t AliTRDrawStream::ReadZSData()
     }
     if (channelcount != channelcountExp)
       MCMError(kAdcChannelsMiss);
     }
     if (channelcount != channelcountExp)
       MCMError(kAdcChannelsMiss);
-    
+
     mcmcount++;
     if (fCurrSm > -1 && fCurrSm < 18) {
       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNMCMs++;
     mcmcount++;
     if (fCurrSm > -1 && fCurrSm < 18) {
       fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNMCMs++;
@@ -1026,8 +1712,8 @@ Int_t AliTRDrawStream::ReadZSData()
     }
 
     if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
     }
 
     if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
-      DumpRaw(Form("Event %i: Det %3i ROB %i MCM %2i", fRawReader->GetEventIndex(), 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
@@ -1036,7 +1722,7 @@ Int_t AliTRDrawStream::ReadZSData()
   // check for missing MCMs (if header suppression is inactive)
   if (((fCurrMajor & 0x1) == 0) && (mcmcount != mcmcountExp)) {
     LinkError(kMissMcmHeaders,
   // check for missing MCMs (if header suppression is inactive)
   if (((fCurrMajor & 0x1) == 0) && (mcmcount != mcmcountExp)) {
     LinkError(kMissMcmHeaders,
-             "No. of MCM headers %i not as expected: %i", 
+             "No. of MCM headers %i not as expected: %i",
              mcmcount, mcmcountExp);
   }
 
              mcmcount, mcmcountExp);
   }
 
@@ -1046,9 +1732,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;
@@ -1061,46 +1747,48 @@ Int_t AliTRDrawStream::ReadNonZSData()
   Int_t lastrobpos = -1;
 
   if (fCurrNtimebins != fNtimebins) {
   Int_t lastrobpos = -1;
 
   if (fCurrNtimebins != fNtimebins) {
-    if (fNtimebins > 0) 
+    if (fNtimebins > 0)
       LinkError(kNtimebinsChanged,
                "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
     fNtimebins = fCurrNtimebins;
   }
       LinkError(kNtimebinsChanged,
                "No. of timebins changed from %i to %i", 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 {
-      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 {
-      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)
        evno = EvNo(*fPayloadCurr);
       else {
     if (EvNo(*fPayloadCurr) != evno) {
       if (evno == -1)
        evno = EvNo(*fPayloadCurr);
       else {
-       MCMError(kPtrgCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
+       MCMError(kEvCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
       }
     }
       }
     }
-    
+
     channelcount = 0;
     channelcountExp = 21;
     int channelno = -1;
     channelcount = 0;
     channelcountExp = 21;
     int channelno = -1;
@@ -1112,41 +1800,42 @@ Int_t AliTRDrawStream::ReadNonZSData()
     fPayloadCurr++;
 
     // ----- reading marked ADC channels -----
     fPayloadCurr++;
 
     // ----- reading marked ADC channels -----
-    while (channelcount < channelcountExp && 
+    while (channelcount < channelcountExp &&
           *(fPayloadCurr) != fgkDataEndmarker) {
       if (channelno < 20)
        channelno++;
           *(fPayloadCurr) != fgkDataEndmarker) {
       if (channelno < 20)
        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) {
            MCMError(kAdcCheckInvalid,
        int check = 0x3 & *fPayloadCurr;
        if (channelno % 2 != 0) { // odd channel
          if (check != 0x2 && channelno < 21) {
            MCMError(kAdcCheckInvalid,
-                    "%i for %2i. ADC word in odd channel %i", 
+                    "%i for %2i. ADC word in odd channel %i",
                     check, adcwc+1, channelno);
          }
        }
        else {                  // even channel
          if (check != 0x3 && channelno < 21) {
            MCMError(kAdcCheckInvalid,
                     check, adcwc+1, channelno);
          }
        }
        else {                  // even channel
          if (check != 0x3 && channelno < 21) {
            MCMError(kAdcCheckInvalid,
-                    "%i for %2i. ADC word in even channel %i", 
+                    "%i for %2i. ADC word in even channel %i",
                     check, adcwc+1, channelno);
          }
        }
                     check, adcwc+1, channelno);
          }
        }
-       
+
        // filling the actual timebin data
        int tb2 = 0x3ff & *fPayloadCurr >> 22;
        int tb1 = 0x3ff & *fPayloadCurr >> 12;
        int tb0 = 0x3ff & *fPayloadCurr >> 2;
        // 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) 
+       if (adcwc != 0 || fCurrNtimebins <= 30)
          fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
        else
          tb0 = -1;
          fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
        else
          tb0 = -1;
@@ -1157,10 +1846,10 @@ Int_t AliTRDrawStream::ReadNonZSData()
        fPayloadCurr++;
       }
 
        fPayloadCurr++;
       }
 
-      if (adcwc != timebins / 3) 
+      if (adcwc != nADCwords)
        MCMError(kAdcDataAbort);
        MCMError(kAdcDataAbort);
-      
-      // adding index 
+
+      // adding index
       if (padcol > 0 && padcol < 144) {
        fSignalIndex->AddIndexRC(row, padcol);
       }
       if (padcol > 0 && padcol < 144) {
        fSignalIndex->AddIndexRC(row, padcol);
       }
@@ -1183,6 +1872,33 @@ Int_t AliTRDrawStream::ReadNonZSData()
   return (fPayloadCurr - start);
 }
 
   return (fPayloadCurr - start);
 }
 
+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++;
+
+  return (fPayloadCurr-start);
+}
+
 Int_t AliTRDrawStream::SeekNextLink()
 {
   // proceed in raw data stream till the next link
 Int_t AliTRDrawStream::SeekNextLink()
 {
   // proceed in raw data stream till the next link
@@ -1202,22 +1918,22 @@ Int_t AliTRDrawStream::SeekNextLink()
   return (fPayloadCurr - start);
 }
 
   return (fPayloadCurr - start);
 }
 
-Bool_t AliTRDrawStream::ConnectTracklets(TTree *trklTree) 
+Bool_t AliTRDrawStream::ConnectTracklets(TTree *trklTree)
 {
   // connect the tracklet tree used to store the tracklet output
 
   fTrackletTree = trklTree;
 {
   // connect the tracklet tree used to store the tracklet output
 
   fTrackletTree = trklTree;
-  if (!fTrackletTree) 
+  if (!fTrackletTree)
     return kTRUE;
 
     return kTRUE;
 
-  if (!fTrackletTree->GetBranch("hc")) 
+  if (!fTrackletTree->GetBranch("hc"))
     fTrackletTree->Branch("hc", &fCurrHC, "hc/I");
     fTrackletTree->Branch("hc", &fCurrHC, "hc/I");
-  else 
+  else
     fTrackletTree->SetBranchAddress("hc", &fCurrHC);
 
     fTrackletTree->SetBranchAddress("hc", &fCurrHC);
 
-  if (!fTrackletTree->GetBranch("trkl")) 
+  if (!fTrackletTree->GetBranch("trkl"))
     fTrackletTree->Branch("trkl", &fTrackletArray);
     fTrackletTree->Branch("trkl", &fTrackletArray);
-  else 
+  else
     fTrackletTree->SetBranchAddress("trkl", &fTrackletArray);
 
   return kTRUE;
     fTrackletTree->SetBranchAddress("trkl", &fTrackletArray);
 
   return kTRUE;
@@ -1225,11 +1941,11 @@ Bool_t AliTRDrawStream::ConnectTracklets(TTree *trklTree)
 
 
 void AliTRDrawStream::EquipmentError(ErrorCode_t err, const char *const msg, ...)
 
 
 void AliTRDrawStream::EquipmentError(ErrorCode_t err, const char *const msg, ...)
-{ 
-  // register error according to error code on equipment level 
+{
+  // 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.fStack  = -1;
   fLastError.fLink   = -1;
   fLastError.fRob    = -1;
@@ -1238,25 +1954,25 @@ void AliTRDrawStream::EquipmentError(ErrorCode_t err, const char *const msg, ...
   (this->*fStoreError)();
 
   va_list ap;
   (this->*fStoreError)();
 
   va_list ap;
-  if (fgErrorDebugLevel[err] > 10) 
+  if (fgErrorDebugLevel[err] > 10)
     AliDebug(fgErrorDebugLevel[err],
     AliDebug(fgErrorDebugLevel[err],
-            Form("Event %6i: Eq. %2d - %s : %s", 
+            Form("Event %6i: Eq. %2d - %s : %s",
                  fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
                  (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
                  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", 
+  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];
                  fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
                  (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
   fErrorFlags |= fgErrorBehav[err];
-}                                                                              
+}
 
 
 void AliTRDrawStream::StackError(ErrorCode_t err, const char *const msg, ...)
 
 
 void AliTRDrawStream::StackError(ErrorCode_t err, const char *const msg, ...)
-{ 
-  // register error according to error code on stack level 
+{
+  // 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.fStack  = fCurrSlot;
   fLastError.fLink   = -1;
   fLastError.fRob    = -1;
@@ -1265,25 +1981,25 @@ void AliTRDrawStream::StackError(ErrorCode_t err, const char *const msg, ...)
   (this->*fStoreError)();
 
   va_list ap;
   (this->*fStoreError)();
 
   va_list ap;
-  if (fgErrorDebugLevel[err] > 0) 
-    AliDebug(fgErrorDebugLevel[err], 
-            Form("Event %6i: Eq. %2d S %i - %s : %s", 
+  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) ));
                  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", 
+  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];
                  fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
                  (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
   fErrorFlags |= fgErrorBehav[err];
-} 
+}
 
 
 void AliTRDrawStream::LinkError(ErrorCode_t err, const char *const msg, ...)
 
 
 void AliTRDrawStream::LinkError(ErrorCode_t err, const char *const msg, ...)
-{ 
-  // register error according to error code on link level 
+{
+  // 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.fStack  = fCurrSlot;
   fLastError.fLink   = fCurrLink;
   fLastError.fRob    = -1;
@@ -1293,24 +2009,24 @@ void AliTRDrawStream::LinkError(ErrorCode_t err, const char *const msg, ...)
 
   va_list ap;
   if (fgErrorDebugLevel[err] > 0)
 
   va_list ap;
   if (fgErrorDebugLevel[err] > 0)
-    AliDebug(fgErrorDebugLevel[err], 
-            Form("Event %6i: Eq. %2d S %i l %2i - %s : %s", 
+    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) ));
                  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", 
+  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];
                  fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
                  (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
   fErrorFlags |= fgErrorBehav[err];
-} 
+}
 
 
 void AliTRDrawStream::ROBError(ErrorCode_t err, const char *const msg, ...)
 
 
 void AliTRDrawStream::ROBError(ErrorCode_t err, const char *const msg, ...)
-{ 
-  // register error according to error code on ROB level 
+{
+  // 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.fStack  = fCurrSlot;
   fLastError.fLink   = fCurrLink;
   fLastError.fRob    = fCurrRobPos;
@@ -1319,25 +2035,25 @@ void AliTRDrawStream::ROBError(ErrorCode_t err, const char *const msg, ...)
   (this->*fStoreError)();
 
   va_list ap;
   (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", 
+  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) ));
                  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], 
+  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];
                  (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
   fErrorFlags |= fgErrorBehav[err];
-} 
+}
 
 
 void AliTRDrawStream::MCMError(ErrorCode_t err, const char *const msg, ...)
 
 
 void AliTRDrawStream::MCMError(ErrorCode_t err, const char *const msg, ...)
-{ 
-  // register error according to error code on MCM level 
+{
+  // 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.fStack  = fCurrSlot;
   fLastError.fLink   = fCurrLink;
   fLastError.fRob    = fCurrRobPos;
@@ -1346,27 +2062,27 @@ void AliTRDrawStream::MCMError(ErrorCode_t err, const char *const msg, ...)
   (this->*fStoreError)();
 
   va_list ap;
   (this->*fStoreError)();
 
   va_list ap;
-  if (fgErrorDebugLevel[err] > 0) 
-    AliDebug(fgErrorDebugLevel[err], 
+  if (fgErrorDebugLevel[err] > 0)
+    AliDebug(fgErrorDebugLevel[err],
             Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
             Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
-                 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err], 
+                 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
                  (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
                  (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
-  else 
+  else
     AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
     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], 
+                 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)
                  (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
   fErrorFlags |= fgErrorBehav[err];
 }
 
 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) 
+  if (errCode > 0 && errCode < kLastErrorCode)
     return fgkErrorMessages[errCode];
     return fgkErrorMessages[errCode];
-  else 
-    return ""; 
-} 
+  else
+    return "";
+}
 
 void AliTRDrawStream::AliTRDrawStats::ClearStats()
 {
 
 void AliTRDrawStream::AliTRDrawStats::ClearStats()
 {
@@ -1406,11 +2122,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;
@@ -1438,30 +2154,145 @@ Bool_t AliTRDrawStream::DumpingMCM(Int_t det, Int_t rob, Int_t mcm)  const
   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 ( ; pos < length; pos++) {
-    title += Form("0x%08x ", start[pos]);
+  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;
+    }
   }
   }
-  AliInfo(title);
+  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;
 }
 
 }
 
-AliTRDrawStream::AliTRDrawStreamError::AliTRDrawStreamError(Int_t error, Int_t sector, Int_t stack, Int_t link, Int_t rob, Int_t mcm) : 
+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),
   fError(error),
   fSector(sector),
   fStack(stack),
-  fLink(link), 
+  fLink(link),
   fRob(rob),
   fMcm(mcm)
 {
   // ctor
 
 }
   fRob(rob),
   fMcm(mcm)
 {
   // ctor
 
 }
+
+void AliTRDrawStream::SortTracklets(TClonesArray *trklArray, TList &sortedTracklets, Int_t *indices)
+{
+  // sort tracklets for referencing from GTU tracks
+
+  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()) ||
+           ((trklA->GetZbin() == trklB->GetZbin()) && (trklA->GetYbin() < trklB->GetYbin()))) {
+         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) {
+       Int_t label = -2; // mark raw tracklets with label -2
+       if (AliTRDtrackletMCM *trklMCM = dynamic_cast<AliTRDtrackletMCM*> (trklNext))
+         label = trklMCM->GetLabel();
+       AliESDTrdTracklet *esdTracklet = new AliESDTrdTracklet(trklNext->GetTrackletWord(), trklNext->GetHCId(), label);
+       sortedTracklets.Add(esdTracklet);
+      }
+
+      // updating tracklet indices as in output
+      if (sortedTracklets.GetEntries() != trklIndex) {
+       indices[2*iDet + 0] = indices[2*iDet + 1] = trklIndex;
+      }
+      else
+       indices[2*iDet + 0] = indices[2*iDet + 1] = -1;
+    }
+  }
+}