- AliMUONRawStreamTrackerHP can also return all header structures.
authorivana <ivana@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 18 Dec 2007 10:46:01 +0000 (10:46 +0000)
committerivana <ivana@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 18 Dec 2007 10:46:01 +0000 (10:46 +0000)
- Added examples to MUONRawStreamTracker.C
(Artur)

MUON/AliMUONRawStreamTracker.cxx
MUON/AliMUONRawStreamTracker.h
MUON/AliMUONRawStreamTrackerHP.cxx
MUON/AliMUONRawStreamTrackerHP.h
MUON/AliMUONTrackerDDLDecoder.h
MUON/AliMUONTrackerDDLDecoderEventHandler.h
MUON/AliMUONVRawStreamTracker.h
MUON/MUONRawStreamTracker.C
MUON/MUONrawLinkDef.h

index 3323407..13c4b7d 100644 (file)
@@ -66,8 +66,7 @@ AliMUONRawStreamTracker::AliMUONRawStreamTracker()
    fCurrentBusStruct(0),
    fCurrentBusStructIndex(0),
    fCurrentDataIndex(0),
-   fDDL(0),
-   fChannelBuffer()
+   fDDL(0)
 {
   ///
   /// create an object to read MUON raw digits
@@ -90,8 +89,7 @@ AliMUONRawStreamTracker::AliMUONRawStreamTracker(AliRawReader* rawReader)
   fCurrentBusStruct(0),
   fCurrentBusStructIndex(0),
   fCurrentDataIndex(0),
-  fDDL(0),
-  fChannelBuffer()
+  fDDL(0)
 {
   ///
   /// ctor with AliRawReader as argument
@@ -145,26 +143,6 @@ AliMUONRawStreamTracker::Next(Int_t& busPatchId,
 }
 
 //______________________________________________________
-UInt_t AliMUONRawStreamTracker::Next(const AliChannelInfo*& channels)
-{
-  /// This method actually just wraps around the single step Next() method
-  /// for now and returns channels one at a time.
-
-  Int_t busPatchId; UShort_t manuId; UChar_t manuChannel; UShort_t adc;
-  Bool_t ok = Next(busPatchId, manuId, manuChannel, adc);
-  if (ok)
-  {
-        fChannelBuffer = AliChannelInfo(busPatchId, manuId, manuChannel, adc);
-        channels = &fChannelBuffer;
-       return 1;
-  }
-  else
-  {
-       return 0;
-  }
-}
-
-//______________________________________________________
 Bool_t
 AliMUONRawStreamTracker::IsDone() const
 {
index 6945f47..5091794 100644 (file)
@@ -46,9 +46,6 @@ class AliMUONRawStreamTracker: public AliMUONVRawStreamTracker {
     virtual Bool_t Next(Int_t& busPatchId, 
                         UShort_t& manuId, UChar_t& manuChannel, 
                         UShort_t& adc);
-
-    /// Returns the next batch of decoded channel data.
-    virtual UInt_t Next(const AliChannelInfo*& channels);
     
     virtual Bool_t NextDDL();
 
@@ -123,8 +120,7 @@ class AliMUONRawStreamTracker: public AliMUONVRawStreamTracker {
     AliMUONBusStruct* fCurrentBusStruct;     //!< for iterator: current bus ptr
     Int_t fCurrentBusStructIndex;            //!< for iterator: current bus index    
     Int_t fCurrentDataIndex;                 //!< for iterator: current data index
-    Int_t  fDDL;                             //!< number of DDL    
-    AliChannelInfo fChannelBuffer;           //!< Single channel buffer for Next() method.
+    Int_t  fDDL;                             //!< number of DDL
     static const Int_t  fgkMaxDDL;           //!< maximum number of DDLs
 
     ClassDef(AliMUONRawStreamTracker, 4)    // base class for reading MUON raw digits
index 909fe1c..1977324 100644 (file)
 /// To gain the most out of the decoder, the Next() method which returns batches
 /// of decoded digit / channel information should be used. That is:
 /// \code
-///   UInt_t Next(const AliChannelInfo*& channels);
+///   const AliBusPatch* Next();
 /// \endcode
 ///
+/// This decoder tries to implement as similar an interface as possible to
+/// AliMUONRawStreamTracker where possible. However certain constructs which
+/// would slow us down too much are avoided.
+///
 /// \author Artur Szostak <artursz@iafrica.com>
 //-----------------------------------------------------------------------------
 
 #include "AliRawReader.h"
 #include "AliLog.h"
 #include <cassert>
+#include <iostream>
+#include <iomanip>
+using std::cout;
+using std::endl;
+using std::hex;
+using std::dec;
 
 /// \cond CLASSIMP
 ClassImp(AliMUONRawStreamTrackerHP)
@@ -53,14 +63,30 @@ AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() :
        AliMUONVRawStreamTracker(),
        fDecoder(),
        fDDL(0),
-       fCurrentChannel(0),
        fBufferSize(8192),
        fBuffer(new UChar_t[8192]),
-       fHadError(kFALSE)
+       fCurrentBusPatch(NULL),
+       fCurrentData(NULL),
+       fEndOfData(NULL),
+       fHadError(kFALSE),
+       fDone(kFALSE)
 {
        ///
        /// Default constructor.
        ///
+       
+       // Must set this flag to get all information about parity errors though
+       // the OnData method. OnError gets them either way.
+       fDecoder.ExitOnError(false);
+       fDecoder.SendDataOnParityError(true);
+
+       fDecoder.GetHandler().SetMaxStructs(
+                       fDecoder.MaxBlocks(),
+                       fDecoder.MaxDSPs(),
+                       fDecoder.MaxBusPatches()
+               );
+
+       fDecoder.GetHandler().SetRawStream(this);
 }
 
 
@@ -68,15 +94,29 @@ AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP(AliRawReader* rawReader) :
        AliMUONVRawStreamTracker(rawReader),
        fDecoder(),
        fDDL(0),
-       fCurrentChannel(0),
        fBufferSize(8192),
        fBuffer(new UChar_t[8192]),
-       fHadError(kFALSE)
+       fCurrentBusPatch(NULL),
+       fCurrentData(NULL),
+       fEndOfData(NULL),
+       fHadError(kFALSE),
+       fDone(kFALSE)
 {
        ///
        /// Constructor with AliRawReader as argument.
        ///
        
+       // Must set this flag to get all information about parity errors though
+       // the OnData method. OnError gets them either way.
+       fDecoder.ExitOnError(false);
+       fDecoder.SendDataOnParityError(true);
+
+       fDecoder.GetHandler().SetMaxStructs(
+                       fDecoder.MaxBlocks(),
+                       fDecoder.MaxDSPs(),
+                       fDecoder.MaxBusPatches()
+               );
+       
        fDecoder.GetHandler().SetRawStream(this);
 }
 
@@ -102,6 +142,7 @@ void AliMUONRawStreamTrackerHP::First()
        assert( GetReader() != NULL );
        
        fDDL = 0;
+       fDone = kFALSE;
        NextDDL();
 }
 
@@ -114,9 +155,7 @@ Bool_t AliMUONRawStreamTrackerHP::NextDDL()
 
        assert( GetReader() != NULL );
        
-       if (IsDone()) return kFALSE;
-       
-       do
+       while (fDDL < GetMaxDDL())
        {
                GetReader()->Reset();
                GetReader()->Select("MUONTRK", fDDL, fDDL);  // Select the DDL file to be read.
@@ -124,8 +163,20 @@ Bool_t AliMUONRawStreamTrackerHP::NextDDL()
                AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1));
                fDDL++;
        }
-       while (fDDL < GetMaxDDL());
-       
+
+       // If we reach the end of the DDL list for this event then reset the
+       // DDL counter, mark the iteration as done and 
+       if (fDDL >= GetMaxDDL())
+       {
+               fDDL = 0;
+               fDone = kTRUE;
+               return kFALSE;
+       }
+       else
+       {
+               fDone = kFALSE;
+       }
+
        AliDebug(3, Form("DDL Number %d\n", fDDL));
        
        Int_t dataSize = GetReader()->GetDataSize(); // in bytes
@@ -166,14 +217,29 @@ Bool_t AliMUONRawStreamTrackerHP::NextDDL()
                // Since we might allocate memory inside OnNewBuffer in the event
                // handler we need to trap any memory allocation exception to be robust.
                result = fDecoder.Decode(fBuffer, dataSize);
+               fHadError = (result == true ? kFALSE : kTRUE);
        }
        catch (const std::bad_alloc&)
        {
                AliError("Could not allocate more buffer space. Cannot decode DDL.");
                return kFALSE;
        }
-       
-       fCurrentChannel = 0;
+
+       // Update the current bus patch pointers.
+       fCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch();
+       if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
+       {
+               fCurrentData = fCurrentBusPatch->GetData();
+               fEndOfData = fCurrentData + fCurrentBusPatch->GetDataCount();
+       }
+       else
+       {
+               // If the DDL did not have any bus patches then mark both fCurrentData
+               // and fEndOfData as NULL so that in Next() we are forced to find the
+               // first non empty DDL.
+               fCurrentData = fEndOfData = NULL;
+       }
+
        fDDL++; // Remember to increment index to next DDL.
        return result;
 }
@@ -184,7 +250,7 @@ Bool_t AliMUONRawStreamTrackerHP::IsDone() const
        /// Indicates whether the iteration is finished or not.
        /// \return kTRUE if we already read all the digits and kFALSE if not.
        
-       return fDDL == GetMaxDDL();
+       return fDone;
 }
 
 
@@ -201,73 +267,169 @@ Bool_t AliMUONRawStreamTrackerHP::Next(
        /// \return kTRUE if we read another digit and kFALSE if we have read all the
        ///    digits already, i.e. at the end of the iteration.
        
-       if (fCurrentChannel < fDecoder.GetHandler().ChannelCount())
+retry:
+       // Check if we still have data to be returned for the current bus patch.
+       if (fCurrentData != fEndOfData)
        {
-               const AliChannelInfo& channel = fDecoder.GetHandler().Channels()[fCurrentChannel];
-               busPatchId = channel.BusPatchId();
-               manuId = channel.ManuId();
-               manuChannel = channel.ChannelId();
-               adc = channel.ADC();
-               fCurrentChannel++;
+               busPatchId = fCurrentBusPatch->GetBusPatchId();
+               AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fCurrentData, manuId, manuChannel, adc);
+               fCurrentData++;
                return kTRUE;
        }
        else
        {
-               if (NextDDL())
+               // We hit the end of the current bus patch so check if we have any more
+               // bus patches to process for the current DDL. If we do, then increment
+               // the current bus patch, make sure it is not the last one and then try
+               // reading the first element again.
+               if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
                {
-                       if (fCurrentChannel < fDecoder.GetHandler().ChannelCount())
+                       fCurrentBusPatch++;
+                       if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
                        {
-                               const AliChannelInfo& channel = fDecoder.GetHandler().Channels()[fCurrentChannel];
-                               busPatchId = channel.BusPatchId();
-                               manuId = channel.ManuId();
-                               manuChannel = channel.ChannelId();
-                               adc = channel.ADC();
-                               fCurrentChannel++;
-                               return kTRUE;
+                               fCurrentData = fCurrentBusPatch->GetData();
+                               fEndOfData = fCurrentData + fCurrentBusPatch->GetDataCount();
+                               goto retry;
                        }
                }
+
+               // This was the last bus patch in the DDL so read in the next one and
+               // try reading the first data element again.
+               // Note: fCurrentBusPatch is set inside NextDDL().
+               if (NextDDL()) goto retry;
        }
        return kFALSE;
 }
 
 
-UInt_t AliMUONRawStreamTrackerHP::Next(const AliChannelInfo*& channels)
+void AliMUONRawStreamTrackerHP::SetMaxBlock(Int_t blk)
 {
-       /// Returns the next batch of decoded channel data.
-       /// [out] \param channels This is filled with a pointer to an array of
-       ///          channels / digits that were decoded. This method does not
-       ///          modify 'channels' if zero is returned.
-       /// \return The number of elements in the array pointed to by 'channels'
-       ///    is returned. If zero is returned then there are no more channels to read.
+       /// Set maximum number of blocks per DDL allowed.
+       fDecoder.MaxBlocks( (UInt_t) blk );
        
-       // Check if we are already at the end of the channels array. If so then we
-       // need to fetch the next non empty DDL.
-       if (fCurrentChannel >= fDecoder.GetHandler().ChannelCount())
+       fDecoder.GetHandler().SetMaxStructs(
+                       fDecoder.MaxBlocks(),
+                       fDecoder.MaxDSPs(),
+                       fDecoder.MaxBusPatches()
+               );
+}
+
+
+void AliMUONRawStreamTrackerHP::SetMaxDsp(Int_t dsp)
+{
+       /// Set maximum number of Dsp per block allowed.
+       fDecoder.MaxDSPs( (UInt_t) dsp );
+       
+       fDecoder.GetHandler().SetMaxStructs(
+                       fDecoder.MaxBlocks(),
+                       fDecoder.MaxDSPs(),
+                       fDecoder.MaxBusPatches()
+               );
+}
+
+
+void AliMUONRawStreamTrackerHP::SetMaxBus(Int_t bus)
+{
+       /// Set maximum number of Buspatch per Dsp allowed.
+       fDecoder.MaxBusPatches( (UInt_t) bus );
+       
+       fDecoder.GetHandler().SetMaxStructs(
+                       fDecoder.MaxBlocks(),
+                       fDecoder.MaxDSPs(),
+                       fDecoder.MaxBusPatches()
+               );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AliMUONRawStreamTrackerHP::AliBlockHeader::Print() const
+{
+       /// Print header to screen.
+       
+       cout << "CRT info"        << endl;
+       if (fHeader == NULL)
        {
-               do
-               {
-                       if (not NextDDL()) return 0;
-               }
-               // Make sure to keep going even for empty DDL payloads:
-               while (fDecoder.GetHandler().ChannelCount() == 0);
+               cout << "Header is NULL" << endl;
+               return;
+       }
+       cout << "DataKey: 0x"     << hex << fHeader->fDataKey << dec << endl;
+       cout << "TotalLength: "   << fHeader->fTotalLength << endl;
+       cout << "Length: "        << fHeader->fLength << endl;
+       cout << "DspId: "         << fHeader->fDSPId << endl;
+       cout << "L0Trigger: "     << fHeader->fL0Trigger << endl;
+       cout << "MiniEventId: "   << fHeader->fMiniEventId<< endl; 
+       cout << "EventId1: "      << fHeader->fEventId1 << endl;
+       cout << "EventId2: "      << fHeader->fEventId2 << endl;
+}
+
+
+void AliMUONRawStreamTrackerHP::AliDspHeader::Print() const
+{
+       /// Print header to screen.
+       
+       cout << "FRT info"        << endl;
+       if (fHeader == NULL)
+       {
+               cout << "Header is NULL" << endl;
+               return;
+       }
+       cout << "DataKey: 0x"     << hex << fHeader->fDataKey << dec << endl;
+       cout << "TotalLength: "   << fHeader->fTotalLength << endl;
+       cout << "Length : "       << fHeader->fLength << endl;
+       cout << "DspId: "         << fHeader->fDSPId << endl;
+       cout << "BlkL1ATrigger: " << fHeader->fBlkL1ATrigger << endl;
+       cout << "MiniEventId: "   << fHeader->fMiniEventId << endl;
+       cout << "L1ATrigger: "    << fHeader->fL1ATrigger << endl;
+       cout << "L1RTrigger: "    << fHeader->fL1RTrigger << endl;
+       cout << "PaddingWord: "   << fHeader->fPaddingWord << endl;
+       cout << "ErrorWord: "     << fHeader->fErrorWord << endl;
+}
+
+
+void AliMUONRawStreamTrackerHP::AliBusPatch::Print(const Option_t* opt) const
+{
+       /// Print header to screen.
+       cout << "Bus patch info" << endl;
+       if (fHeader == NULL)
+       {
+               cout << "Header is NULL" << endl;
+               return;
+       }
+       cout << "DataKey: 0x"    << hex << fHeader->fDataKey << dec << endl;
+       cout << "fTotalLength: " << fHeader->fTotalLength << endl;
+       cout << "fLength: "      << fHeader->fLength << endl;
+       cout << "fBusPatchId: "  << fHeader->fBusPatchId << endl;
+
+       if (TString(opt).Contains("all"))
+       {
+               for (UInt_t i = 0; i < fHeader->fLength; ++i)
+                       cout << "Data["<< i << "] = " << fData[i] << endl;
        }
-       channels = fDecoder.GetHandler().Channels() + fCurrentChannel;
-       return fDecoder.GetHandler().ChannelCount() - fCurrentChannel;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 AliMUONRawStreamTrackerHP::AliDecoderEventHandler::AliDecoderEventHandler() :
-       fBusPatchId(0),
-       fChannelCount(0),
-       fMaxChannels(8192),
-       fChannelBuffer(new AliChannelInfo[8192]),
        fRawStream(NULL),
-       fBufferStart(NULL)
+       fBufferStart(NULL),
+       fBlockCount(0),
+       fBlocks(NULL),
+       fDSPs(NULL),
+       fBusPatches(NULL),
+       fEndOfBusPatches(NULL),
+       fMaxChannels(8192),
+       fParityOk(new Bool_t[8192]),
+       fCurrentBlock(NULL),
+       fCurrentDSP(NULL),
+       fCurrentBusPatch(NULL),
+       fCurrentParityOkFlag(NULL),
+       fParityErrors(0),
+       fGlitchErrors(0),
+       fPaddingErrors(0),
+       fWarnings(kTRUE)
 {
-       /// Default constructor initialises the internal buffer to store decoded
-       /// channel / digit data to 8192 elements.
-       /// This array will grow dynamically if needed.
+       /// Default constructor initialises the internal parity flags buffer to
+       /// store 8192 elements. This array will grow dynamically if needed.
 }
 
 
@@ -275,12 +437,47 @@ AliMUONRawStreamTrackerHP::AliDecoderEventHandler::~AliDecoderEventHandler()
 {
        /// Default destructor cleans up the allocated memory.
        
-       if (fChannelBuffer != NULL)
+       if (fParityOk != NULL) delete [] fParityOk;
+       if (fBlocks != NULL) delete [] fBlocks;
+       if (fDSPs != NULL) delete [] fDSPs;
+       if (fBusPatches != NULL) delete [] fBusPatches;
+}
+
+
+void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::SetMaxStructs(
+               UInt_t maxBlocks, UInt_t maxDsps, UInt_t maxBusPatches
+       )
+{
+       /// Sets the maximum number of structures allowed.
+       
+       // Start by clearing the current arrays.
+       if (fBlocks != NULL)
+       {
+               delete [] fBlocks;
+               fBlocks = NULL;
+       }
+       if (fDSPs != NULL)
        {
-               delete [] fChannelBuffer;
+               delete [] fDSPs;
+               fDSPs = NULL;
        }
+       if (fBusPatches != NULL)
+       {
+               delete [] fBusPatches;
+               fBusPatches = NULL;
+       }
+       fCurrentBlock = NULL;
+       fCurrentDSP = NULL;
+       fCurrentBusPatch = NULL;
+       
+       // Allocate new memory.
+       fBlocks = new AliBlockHeader[maxBlocks];
+       fDSPs = new AliDspHeader[maxBlocks*maxDsps];
+       fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches];
+       fEndOfBusPatches = fEndOfBusPatches;
 }
 
+
 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer(
                const void* buffer, UInt_t bufferSize
        )
@@ -290,56 +487,42 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer(
        /// \param buffer  The pointer to the buffer storing the DDL payload.
        /// \param bufferSize  The size of the buffer in bytes.
 
+       assert( fRawStream != NULL );
+       
        // remember the start of the buffer to be used in OnError.
        fBufferStart = buffer;
-       
-       // Reset the number of channels found.
-       fChannelCount = 0;
-       
-       // Check if we will have enough space in the fChannelBuffer array.
+
+       // Reset error counters.
+       fParityErrors = 0;
+       fGlitchErrors = 0;
+       fPaddingErrors = 0;
+
+       // Check if we will have enough space in the fParityOk array.
        // If we do not then we need to resize the array.
        // bufferSize / sizeof(UInt_t) will be a safe over estimate of the
        // number of channels that we will find.
-       UInt_t maxPossibleChannels = bufferSize / sizeof(UInt_t);
-       if (maxPossibleChannels > fMaxChannels)
+       UInt_t maxChannelsPossible = bufferSize / sizeof(UInt_t);
+       if (maxChannelsPossible > fMaxChannels)
        {
-               if (fChannelBuffer != NULL)
+               if (fParityOk != NULL)
                {
-                       delete [] fChannelBuffer;
-                       fChannelBuffer = NULL;
+                       delete [] fParityOk;
+                       fParityOk = NULL;
                        fMaxChannels = 0;
                }
-               fChannelBuffer = new AliChannelInfo[maxPossibleChannels];
-               fMaxChannels = maxPossibleChannels;
+               fParityOk = new Bool_t[maxChannelsPossible];
+               fMaxChannels = maxChannelsPossible;
        }
-}
-
-
-void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBusPatch(
-               const AliMUONBusPatchHeaderStruct* header, const void* /*data*/
-       )
-{
-       /// This is called by the high performance decoder when a new bus patch
-       /// is found within the DDL payload. All we do is remember the bus patch ID.
-       /// \param header  The bus patch header structure.
-       /// \param data  The bus patch data (not used in this method).
        
-       fBusPatchId = header->fBusPatchId;
-}
-
-
-void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnData(UInt_t data)
-{
-       /// This is called by the high performance decoder when a new bus patch
-       /// is found within the DDL payload. All we do is remember the bus patch ID.
-       /// \param data  The bus patch data (not used in this method).
-       
-       assert( fChannelCount < fMaxChannels );
-       
-       UShort_t manuId; UChar_t channelId; UShort_t adc;
-       UnpackADC(data, manuId, channelId, adc);
-       fChannelBuffer[fChannelCount] = AliChannelInfo(fBusPatchId, manuId, channelId, adc);
-       fChannelCount++;
+       // Reset the current pointers which will be used to track where we need to
+       // fill fBlocks, fDSPs, fBusPatches and the parity flag. We have to subtract
+       // one space because we will increment the pointer the first time in the
+       // OnNewXZY methods.
+       fCurrentBlock = fBlocks-1;
+       fCurrentDSP = fDSPs-1;
+       fCurrentBusPatch = fBusPatches-1;
+       fCurrentParityOkFlag = fParityOk-1;
+       fBlockCount = 0;
 }
 
 
@@ -358,18 +541,64 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError(
        assert( fRawStream != NULL );
        assert( fRawStream->GetReader() != NULL );
        
-       const char* msg = ErrorCodeToMessage(error);
-       unsigned long pos = (unsigned long)location - (unsigned long)fBufferStart;
-       
+       Char_t* message = NULL;
+       UInt_t word = 0;
+
        switch (error)
        {
+       case kGlitchFound:
+               message = Form(
+                       "Glitch error detected in DSP %d, skipping event ",
+                       fCurrentBlock->GetDspId()
+               );
+               fRawStream->GetReader()->AddMajorErrorLog(error, message);
+               break;
+
        case kBadPaddingWord:
+               // We subtract 1 from the current numbers of blocks, DSPs
+               // and bus patches to get the indices.
+               message = Form(
+                       "Padding word error for iBlock %d, iDsp %d, iBus %d\n", 
+                       fBlockCount-1,
+                       fCurrentBlock->GetDspCount()-1,
+                       fCurrentDSP->GetBusPatchCount()-1
+               );
+               fRawStream->GetReader()->AddMinorErrorLog(error, message);
+               break;
+
        case kParityError:
-               fRawStream->GetReader()->AddMinorErrorLog(error, Form("%s [At byte: %d]", msg, pos));
+               // location points to the incorrect data word and
+               // fCurrentBusPatch->GetData() returns a pointer to the start of
+               // bus patches data, so the difference divided by 4 gives the 32
+               // bit word number.
+               word = ((unsigned long)location - (unsigned long)fCurrentBusPatch->GetData())
+                               / sizeof(UInt_t);
+               message = Form(
+                       "Parity error in word %d for manuId %d and channel %d in buspatch %d\n", 
+                       word,
+                       fCurrentBusPatch->GetManuId(word),
+                       fCurrentBusPatch->GetChannelId(word),
+                       fCurrentBusPatch->GetBusPatchId()
+               );
+               fRawStream->GetReader()->AddMinorErrorLog(error, message);
                break;
+
        default:
-               fRawStream->GetReader()->AddMajorErrorLog(error, Form("%s [At byte: %d]", msg, pos));
+               message = Form(
+                       "%s (At byte %d in DDL.)",
+                       ErrorCodeToMessage(error),
+                       (unsigned long)location - (unsigned long)fBufferStart
+               );
+               fRawStream->GetReader()->AddMajorErrorLog(error, message);
                break;
        }
+
+       if (fWarnings)
+       {
+               AliWarningGeneral(
+                               "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",
+                               message
+                       );
+       }
 }
 
index f4fbc8e..8787ad9 100644 (file)
@@ -19,6 +19,8 @@
 class AliMUONRawStreamTrackerHP : public AliMUONVRawStreamTracker
 {
 public:
+       class AliDspHeader;
+       class AliBusPatch;
 
        /// Default constructor.
        AliMUONRawStreamTrackerHP();
@@ -42,7 +44,7 @@ public:
        
        /// Nothing is actually done in the AddErrorMessage method because we log
        /// the error messages as we find them in AliDecoderEventHandler::OnError().
-       virtual void AddErrorMessage() {};
+       virtual void AddErrorMessage() { };
        
        /// Advance one step in the iteration. Returns false if finished.
        virtual Bool_t Next(Int_t& busPatchId,
@@ -50,7 +52,13 @@ public:
                                UShort_t& adc);
        
        /// Returns the next batch of decoded channel data.
-       virtual UInt_t Next(const AliChannelInfo*& channels);
+       const AliBusPatch* Next()
+       {
+               do {
+                       if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch()) return fCurrentBusPatch++;
+               } while (NextDDL());
+               return NULL;
+       }
        
        /// Return maximum number of blocks per DDL allowed.
        virtual Int_t GetMaxBlock() const { return (Int_t) fDecoder.MaxBlocks(); }
@@ -60,17 +68,416 @@ public:
        virtual Int_t GetMaxBus() const { return (Int_t) fDecoder.MaxBusPatches(); }
        
        /// Set maximum number of blocks per DDL allowed.
-       virtual void SetMaxBlock(Int_t blk) { fDecoder.MaxBlocks( (UInt_t) blk ); }
+       virtual void SetMaxBlock(Int_t blk);
        /// Set maximum number of Dsp per block allowed.
-       virtual void SetMaxDsp(Int_t dsp) { fDecoder.MaxDSPs( (UInt_t) dsp ); }
+       virtual void SetMaxDsp(Int_t dsp);
        /// Set maximum number of Buspatch per Dsp allowed.
-       virtual void SetMaxBus(Int_t bus) { fDecoder.MaxBusPatches( (UInt_t) bus ); }
+       virtual void SetMaxBus(Int_t bus);
        
        /// Return number of the current DDL.
        virtual Int_t GetDDL() const { return fDDL - 1; }
        
        /// check error/Warning presence
        virtual Bool_t IsErrorMessage() const { return fHadError; }
+       
+       /// Get number of parity errors
+       Int_t   GetParityErrors() const
+       {
+               return (Int_t) fDecoder.GetHandler().ParityErrorCount();
+       }
+
+       /// Get number of glitch errors
+       Int_t   GetGlitchErrors() const
+       {
+               return (Int_t) fDecoder.GetHandler().GlitchErrorCount();
+       }
+
+       /// Get number of padding word errors
+       Int_t   GetPaddingErrors() const
+       {
+               return (Int_t) fDecoder.GetHandler().PaddingErrorCount();
+       }
+
+       /// Set warnings flag to disable warnings on data errors.
+       void DisableWarnings() { fDecoder.GetHandler().Warnings(kFALSE); }
+       /// Set warnings flag to enable warnings on data errors.
+       void EnableWarnings() { fDecoder.GetHandler().Warnings(kTRUE); }
+
+       /// Returns the "try to recover from errors" flag.
+       Bool_t TryRecover() const { return Bool_t(fDecoder.TryRecover()); }
+       
+       /// Sets the "try to recover from errors" flag.
+       /// i.e. should the decoder try to recover from errors found in the
+       /// payload headers.
+       void TryRecover(Bool_t value) { fDecoder.TryRecover(bool(value)); }
+       
+       /// Light weight interface class to the block header data.
+       class AliBlockHeader
+       {
+       public:
+               /// Default constructor.
+               AliBlockHeader(
+                               AliDspHeader* dspArray = NULL,
+                               const AliMUONBlockHeaderStruct* header = NULL
+                       )
+                       : fNext(NULL), fDspCount(0), fFirstDsp(dspArray), fHeader(header)
+               {
+               }
+               
+               /// Implement shallow copying in the copy constructor.
+               AliBlockHeader(const AliBlockHeader& o) :
+                       fNext(o.fNext), fDspCount(o.fDspCount), fFirstDsp(o.fFirstDsp), fHeader(o.fHeader)
+               {
+               }
+               
+               /// Implement shallow copying in the assignment operator.
+               AliBlockHeader& operator = (const AliBlockHeader& object)
+               {
+                       memcpy(this, &object, sizeof(AliBlockHeader));
+                       return *this;
+               }
+       
+               /// Default destructor.
+               ~AliBlockHeader() {};
+       
+               /// Return data key word for CRT header
+               Int_t   GetDataKey()        const {assert(fHeader != NULL); return fHeader->fDataKey;}
+               /// Return total length of block structure (w/o padding word)
+               Int_t   GetTotalLength()    const {assert(fHeader != NULL); return fHeader->fTotalLength;}
+               /// Return length of raw data
+               Int_t   GetLength()         const {assert(fHeader != NULL); return fHeader->fLength;}
+               /// Return Dsp id
+               Int_t   GetDspId()          const {assert(fHeader != NULL); return fHeader->fDSPId;}
+               /// Return L0 trigger word
+               Int_t   GetL0Trigger()      const {assert(fHeader != NULL); return fHeader->fL0Trigger;}
+               /// Return Bunch Crossing for mini-event id (see TDR chapter 8)
+               Int_t   GetMiniEventId()    const {assert(fHeader != NULL); return fHeader->fMiniEventId;}
+               /// Return Event Id in bunch crossing
+               Int_t   GetEventId1()       const {assert(fHeader != NULL); return fHeader->fEventId1;}
+               /// Return Event Id in orbit number
+               Int_t   GetEventId2()       const {assert(fHeader != NULL); return fHeader->fEventId2;}
+       
+               /// Return the header's raw data.
+               const AliMUONBlockHeaderStruct* GetHeader() {return fHeader;}
+               
+               /// Return the next block header.
+               const AliBlockHeader* Next() const { return fNext; }
+               
+               /// Returns the first AliDspHeader class in this block.
+               const AliDspHeader* GetFirstDspHeader() const { return fFirstDsp; }
+               
+               /// Returns the number of DSPs within this block.
+               UInt_t GetDspCount() const { return fDspCount; }
+       
+               /// Return the i'th DSP in this block.
+               const AliDspHeader* GetDspHeader(UInt_t i) const
+               {
+                       return i < fDspCount ? GetFirstDspHeader() + i : NULL;
+               }
+               
+               /// Sets the next block header.
+               void SetNext(const AliBlockHeader* next) { fNext = next; }
+
+               /// Increments the DSP count.
+               void IncDspCount() { fDspCount++; };
+               
+               /// Print the contents of the header to screen.
+               void Print() const;
+       
+       private:
+       
+               const AliBlockHeader* fNext;  ///< Pointer to next block.
+               UInt_t fDspCount;    ///< The number of AliDspHeader objects found in the array pointed to by fFirstDsp.
+               const AliDspHeader* fFirstDsp;  ///< The first DSP associated with this block.
+               const AliMUONBlockHeaderStruct*  fHeader;  ///< Pointer to header in DDL payload.
+       };
+       
+       /// Light weight interface class to the DSP header data.
+       class AliDspHeader
+       {
+       public:
+               /// Default constructor.
+               AliDspHeader(
+                               const AliBlockHeader* block = NULL,
+                               const AliBusPatch* busPatchArray = NULL,
+                               const AliMUONDSPHeaderStruct* header = NULL
+                       ) :
+                       fBlock(block), fNext(NULL), fBusPatchCount(0),
+                       fFirstBusPatch(busPatchArray), fHeader(header)
+               {
+               }
+               
+               /// Implement shallow copying in the copy constructor.
+               AliDspHeader(const AliDspHeader& o) :
+                       fBlock(o.fBlock), fNext(o.fNext), fBusPatchCount(o.fBusPatchCount),
+                       fFirstBusPatch(o.fFirstBusPatch), fHeader(o.fHeader)
+               {
+               }
+               
+               /// Implement shallow copying in the assignment operator.
+               AliDspHeader& operator = (const AliDspHeader& object)
+               {
+                       memcpy(this, &object, sizeof(AliDspHeader));
+                       return *this;
+               }
+       
+               /// Default destructor.
+               ~AliDspHeader() {};
+       
+               /// Return Data key word for FRT header
+               Int_t   GetDataKey()        const {assert(fHeader != NULL); return fHeader->fDataKey;}
+               /// Return total length of block structure
+               Int_t   GetTotalLength()    const {assert(fHeader != NULL); return fHeader->fTotalLength;}
+               /// Return length of raw data
+               Int_t   GetLength()         const {assert(fHeader != NULL); return fHeader->fLength;}
+               /// Return Dsp id
+               Int_t   GetDspId()          const {assert(fHeader != NULL); return fHeader->fDSPId;}
+               /// Return L1 accept in Block Structure (CRT)
+               Int_t   GetBlkL1ATrigger()  const {assert(fHeader != NULL); return fHeader->fBlkL1ATrigger;}
+               /// Return Mini Event Id in bunch crossing
+               Int_t   GetMiniEventId()    const {assert(fHeader != NULL); return fHeader->fMiniEventId;}
+               /// Return Number of L1 accept in DSP Structure (FRT)
+               Int_t   GetL1ATrigger()     const {assert(fHeader != NULL); return fHeader->fL1ATrigger;}
+               /// Return Number of L1 reject in DSP Structure (FRT)
+               Int_t   GetL1RTrigger()     const {assert(fHeader != NULL); return fHeader->fL1RTrigger;}
+               /// Return padding dummy word for 64 bits transfer
+               UInt_t  GetPaddingWord()    const {assert(fHeader != NULL); return fHeader->fPaddingWord;}
+               /// Return Error word
+               Int_t   GetErrorWord()      const {assert(fHeader != NULL); return fHeader->fErrorWord;}
+       
+               /// Return raw data of header
+               const AliMUONDSPHeaderStruct* GetHeader() {return fHeader;}
+               
+               /// Return the parent block header.
+               const AliBlockHeader* GetBlockHeader() const { return fBlock; }
+               
+               /// Return the next DSP header.
+               const AliDspHeader* Next() const { return fNext; }
+               
+               /// Returns the first AliBusPatch class in this DSP.
+               const AliBusPatch* GetFirstBusPatch() const { return fFirstBusPatch; }
+               
+               /// Returns the number of bus patches within this DSP.
+               UInt_t GetBusPatchCount() const { return fBusPatchCount; }
+       
+               /// Return the i'th bus patch in this DSP.
+               const AliBusPatch* GetBusPatch(UInt_t i) const
+               {
+                       return i < fBusPatchCount ? GetFirstBusPatch() + i : NULL;
+               }
+       
+               /// Sets the next DSP header.
+               void SetNext(const AliDspHeader* next) { fNext = next; }
+
+               /// Increments the bus patch count.
+               void IncBusPatchCount() { fBusPatchCount++; };
+               
+               /// Print the contents of the header to screen.
+               void Print() const;
+       
+       private:
+       
+               const AliBlockHeader* fBlock;  ///< Pointer to parent block structure.
+               const AliDspHeader* fNext;  ///< Pointer to next DSP.
+               UInt_t fBusPatchCount;    ///< The number of AliDspHeader objects found in the array pointed to by fFirstBusPatch
+               const AliBusPatch* fFirstBusPatch;  ///< The first bus patch of this DSP.
+               const AliMUONDSPHeaderStruct*  fHeader;  ///< Pointer to header in DDL payload.
+       };
+       
+       /// Light weight interface class to the bus patch data.
+       class AliBusPatch
+       {
+       public:
+               /// Default constructor.
+               AliBusPatch(
+                               const AliDspHeader* dsp = NULL,
+                               const AliMUONBusPatchHeaderStruct* header = NULL,
+                               const UInt_t* data = NULL,
+                               const Bool_t* parityOk = NULL
+                       ) :
+                       fDSP(dsp),
+                       fNext(NULL),
+                       fHeader(header),
+                       fData(data),
+                       fParityOk(parityOk)
+               {
+               }
+               
+               /// Implement shallow copying in the copy constructor.
+               AliBusPatch(const AliBusPatch& o) :
+                       fDSP(o.fDSP),
+                       fNext(o.fNext),
+                       fHeader(o.fHeader),
+                       fData(o.fData),
+                       fParityOk(o.fParityOk)
+               {
+               }
+               
+               /// Implement shallow copying in the assignment operator.
+               AliBusPatch& operator = (const AliBusPatch& object)
+               {
+                       memcpy(this, &object, sizeof(AliBusPatch));
+                       return *this;
+               }
+       
+               /// Default destructor.
+               ~AliBusPatch() {};
+               
+               /// Return Data key word for bus patch header.
+               Int_t   GetDataKey()     const {assert(fHeader != NULL); return fHeader->fDataKey;}
+               /// Return total length of buspatch structure
+               Int_t   GetTotalLength() const {assert(fHeader != NULL); return fHeader->fTotalLength;}
+               /// Return length of raw data
+               Int_t   GetLength()      const {assert(fHeader != NULL); return fHeader->fLength;}
+               /// Return bus patch id
+               Int_t   GetBusPatchId()  const {assert(fHeader != NULL); return fHeader->fBusPatchId;}
+
+               /// Return raw data of header
+               const AliMUONBusPatchHeaderStruct* GetHeader() {return fHeader;}
+               /// Return raw digit data
+               const UInt_t* GetData()  const {return fData;}
+               /// Returns the number of raw data words within this bus patch.
+               UInt_t GetDataCount() const { return (UInt_t)GetLength(); }
+
+               /// Returns the parity bit of the n'th raw data word.
+               Char_t GetParity(UInt_t n) const
+               {
+                       assert( fHeader != NULL and n < fHeader->fLength );
+                       return (Char_t)(fData[n] >> 31) &  0x1;
+               }
+               
+               /// Returns the MANU ID of the n'th raw data word.
+               UShort_t GetManuId(UInt_t n) const
+               {
+                       assert( fHeader != NULL and n < fHeader->fLength );
+                       return (UShort_t)(fData[n] >> 18) &  0x7FF;
+               }
+               
+               /// Returns the channel ID of the n'th raw data word.
+               UChar_t GetChannelId(UInt_t n) const
+               {
+                       assert( fHeader != NULL and n < fHeader->fLength );
+                       return (Char_t)(fData[n] >> 12) & 0x3F;
+               }
+               
+               /// Returns the charge/signal of the n'th raw data word.
+               UShort_t GetCharge(UInt_t n) const
+               {
+                       assert( fHeader != NULL and n < fHeader->fLength );
+                       return (UShort_t)(fData[n] & 0xFFF);
+               }
+               
+               /// Returns the n'th raw data word.
+               UInt_t GetData(UInt_t n) const
+               {
+                       assert( fHeader != NULL and n < fHeader->fLength );
+                       return fData[n];
+               }
+               
+               /// Returns kTRUE if the parity of the n'th raw data word is OK
+               /// and kFALSE otherwise.
+               Bool_t IsParityOk(UInt_t n) const
+               {
+                       assert( fHeader != NULL and n < fHeader->fLength );
+                       return fParityOk[n];
+               }
+               
+               /// Unpacks and returns the fields of the n'th raw data word. kTRUE
+               /// is returned if the data word's parity was OK and kFALSE otherwise.
+               Bool_t GetData(UInt_t n, UShort_t& manuId, UChar_t& channelId, UShort_t& adc) const
+               {
+                       assert( fHeader != NULL and n < fHeader->fLength );
+                       AliMUONTrackerDDLDecoderEventHandler::UnpackADC(fData[n], manuId, channelId, adc);
+                       return fParityOk[n];
+               }
+               
+               /// Return the parent block header.
+               const AliDspHeader* GetDspHeader() const { return fDSP; }
+               
+               /// Return the next bus patch header.
+               const AliBusPatch* Next() const { return fNext; }
+               
+               /// Sets the next bus patch.
+               void SetNext(const AliBusPatch* next) { fNext = next; }
+               
+               /// Print the contents of the bus patch to screen.
+               void Print(const Option_t* opt = "") const;
+       
+       private:
+       
+               const AliDspHeader* fDSP;   ///< The DSP this bus patch belongs to.
+               const AliBusPatch* fNext;  ///< Next bus patch object in the DSP.
+               const AliMUONBusPatchHeaderStruct*  fHeader;  ///< Pointer to bus patch in DDL payload.
+               const UInt_t* fData;  ///< Pointer to the bus patch data.
+               const Bool_t* fParityOk;  ///< Array of flags indicating if the parity of the given data word in fData is good or not.          
+       };
+       
+       /// Return the number of blocks in the DDL payload.
+       UInt_t GetBlockCount() const
+       {
+               return fDecoder.GetHandler().BlockCount();
+       }
+       
+       /// Return the first block header.
+       const AliBlockHeader* GetFirstBlockHeader() const
+       {
+               return fDecoder.GetHandler().BlockHeader(0);
+       }
+       
+       /// Return the i'th block header or NULL if not found.
+       const AliBlockHeader* GetBlockHeader(UInt_t i) const
+       {
+               return fDecoder.GetHandler().BlockHeader(i);
+       }
+       
+       /// Returns the number of DSPs for the given block number.
+       UInt_t GetDspCount(UInt_t block) const
+       {
+               const AliBlockHeader* b = GetBlockHeader(block);
+               return b != NULL ? b->GetDspCount() : 0;
+       }
+       
+       /// Returns the i'th DSP header for the given block number or NULL if not found.
+       const AliDspHeader* GetDspHeader(UInt_t block, UInt_t i) const
+       {
+               const AliBlockHeader* b = GetBlockHeader(block);
+               return b != NULL ? b->GetDspHeader(i) : NULL;
+       }
+       
+       /// Returns the number of bus patches for the given block and dsp number.
+       UInt_t GetBusPatchCount(UInt_t block, UInt_t dsp) const
+       {
+               const AliDspHeader* d = GetDspHeader(block, dsp);
+               return d != NULL ? d->GetBusPatchCount() : 0;
+       }
+       
+       /// Returns the i'th bus patch for the given block and dsp.
+       const AliBusPatch* GetBusPatch(UInt_t block, UInt_t dsp, UInt_t i) const
+       {
+               const AliDspHeader* d = GetDspHeader(block, dsp);
+               return d != NULL ? d->GetBusPatch(i) : NULL;
+       }
+
+       /// Returns the current bus patch being decoded or NULL if none found.
+       const AliBusPatch* CurrentBusPatch() const
+       {
+               return (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch()) ?
+                       fCurrentBusPatch : NULL;
+       }
+
+       /// Returns the current DSP being decoded or NULL if none found.
+       const AliDspHeader* CurrentDspHeader() const
+       {
+               const AliBusPatch* busPatch = CurrentBusPatch();
+               return (busPatch != NULL) ? busPatch->GetDspHeader() : NULL;
+       }
+
+       /// Returns the current block header being decoded or NULL if none found.
+       const AliBlockHeader* CurrentBlockHeader() const
+       {
+               const AliDspHeader* dsp = CurrentDspHeader();
+               return (dsp != NULL) ? dsp->GetBlockHeader() : NULL;
+       }
 
 private:
 
@@ -94,25 +501,89 @@ private:
                /// Default destructor.
                virtual ~AliDecoderEventHandler();
                
+               /// Sets the internal arrays based on the maximum number of structures allowed.
+               void SetMaxStructs(UInt_t maxBlocks, UInt_t maxDsps, UInt_t maxBusPatches);
+               
                /// Sets the raw stream object which should be the parent of this class.
                void SetRawStream(AliMUONVRawStreamTracker* rawStream) { fRawStream = rawStream; }
                
-               /// Return the number of channels in the buffer returned by Channels().
-               UInt_t ChannelCount() const { return fChannelCount; }
+               /// Return the number of blocks found in the payload.
+               UInt_t BlockCount() const { return fBlockCount; };
                
-               /// Return the buffer of decoded channel data.
-               const AliChannelInfo* Channels() const { return fChannelBuffer; }
+               /// Return the i'th block structure.
+               const AliBlockHeader* BlockHeader(UInt_t i) const
+               {
+                       return i < fBlockCount ? &fBlocks[i] : NULL;
+               }
+
+               /// Return the first bus patch decoded.
+               const AliBusPatch* FirstBusPatch() const { return fBusPatches; }
+
+               /// Returns the marker to the end of bus patches. i.e. one position past the last bus patch.
+               const AliBusPatch* EndOfBusPatch() const { return fEndOfBusPatches; }
+
+               /// Returns the number of parity errors found in the DDL.
+               UInt_t ParityErrorCount() const { return fParityErrors; }
+               /// Returns the number of glitch errors found in the DDL.
+               UInt_t GlitchErrorCount() const { return fGlitchErrors; }
+               /// Returns the number of padding errors found in the DDL.
+               UInt_t PaddingErrorCount() const { return fPaddingErrors; }
+
+               /// Returns the warnings flag.
+               Bool_t Warnings() const { return fWarnings; }
+               /// Sets the warnings flag.
+               void Warnings(Bool_t value) { fWarnings = value; }
                
                // The following methods are inherited from AliMUONTrackerDDLDecoderEventHandler:
                
                /// New buffer handler.
                void OnNewBuffer(const void* buffer, UInt_t bufferSize);
+
+               /// End of buffer handler marks the end of bus patches.
+               void OnEndOfBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/)
+               {
+                       fEndOfBusPatches = fCurrentBusPatch+1;
+               }
+               
+               /// New block handler is called by the decoder whenever a new block
+               /// structure is found. We just mark the new block and increment the
+               /// internal counter.
+               void OnNewBlock(const AliMUONBlockHeaderStruct* header, const void* /*data*/)
+               {
+                       assert( fBlockCount < (UInt_t)fRawStream->GetMaxBlock() and header != NULL );
+                       if (fBlockCount > 0) fCurrentBlock->SetNext(fCurrentBlock+1);  // Link the block unless it is the first one.
+                       *(++fCurrentBlock) = AliBlockHeader(fCurrentDSP+1, header);
+                       fBlockCount++;
+               }
+               
+               /// New DSP handler is called by the decoder whenever a new DSP
+               /// structure is found. We just mark the DSP and increment the
+               /// appropriate counters.
+               void OnNewDSP(const AliMUONDSPHeaderStruct* header, const void* /*data*/)
+               {
+                       assert( fCurrentBlock->GetDspCount() < (UInt_t)fRawStream->GetMaxDsp() and header != NULL );
+                       if (fCurrentBlock->GetDspCount() > 0) fCurrentDSP->SetNext(fCurrentDSP+1); // Link the DSP unless it is the first one.
+                       *(++fCurrentDSP) = AliDspHeader(fCurrentBlock, fCurrentBusPatch+1, header);
+                       fCurrentBlock->IncDspCount();
+               }
                
                /// New bus patch handler.
-               void OnNewBusPatch(const AliMUONBusPatchHeaderStruct* header, const void* data);
+               /// This is called by the high performance decoder when a new bus patch
+               /// is found within the DDL payload.
+               void OnNewBusPatch(const AliMUONBusPatchHeaderStruct* header, const void* data)
+               {
+                       assert( fCurrentDSP->GetBusPatchCount() < (UInt_t)fRawStream->GetMaxBus() and header != NULL and data != NULL );
+                       if (fCurrentDSP->GetBusPatchCount() > 0) fCurrentBusPatch->SetNext(fCurrentBusPatch+1); // Link the bus patch unless it is the first one.
+                       *(++fCurrentBusPatch) = AliBusPatch(fCurrentDSP, header, reinterpret_cast<const UInt_t*>(data), fCurrentParityOkFlag+1);
+                       fCurrentDSP->IncBusPatchCount();
+               }
                
                /// Raw data word handler.
-               void OnData(UInt_t data);
+               void OnData(UInt_t /*data*/, bool parityError)
+               {
+                       assert( fCurrentParityOkFlag < fParityOk + fMaxChannels );
+                       *(++fCurrentParityOkFlag) = Bool_t(not parityError);
+               }
                
                /// Error handler.
                void OnError(ErrorCode error, const void* location);
@@ -125,22 +596,37 @@ private:
                 /// Not implemented
                AliDecoderEventHandler& operator = (const AliDecoderEventHandler& /*obj*/);
 
-               Int_t fBusPatchId;     //!< The bus patch ID of the current bus patch being decoded.
-               UInt_t fChannelCount;  //!< Number of elements in fChannelBuffer.
-               UInt_t fMaxChannels;   //!< Maximum number of elements that can be stored in fChannelBuffer.
-               AliChannelInfo* fChannelBuffer;  //!< Buffer of decoded channel structures.
                AliMUONVRawStreamTracker* fRawStream; //!< Pointer to the parent raw stream object.
                const void* fBufferStart;   //!< Pointer to the start of the current DDL payload buffer.
+               UInt_t fBlockCount;  //!< Number of blocks filled in fBlocks.
+               AliBlockHeader* fBlocks;  //!< Array of blocks. [0..fMaxBlocks-1]
+               AliDspHeader* fDSPs;      //!< Array of DSPs. [0..fMaxDsps*fMaxBlocks-1]
+               AliBusPatch* fBusPatches; //!< Array of bus patches. [0..fMaxBusPatches*fMaxDsps*fMaxBlocks-1]
+               AliBusPatch* fEndOfBusPatches;  //!< Marks the last bus patch.
+               UInt_t fMaxChannels;   //!< Maximum number of elements that can be stored in fParityOk.
+               Bool_t* fParityOk;     //!< Array of flags for indicating if the parity is good for a raw data word.
+               AliBlockHeader* fCurrentBlock;  //!< Current block in fBlocks.
+               AliDspHeader* fCurrentDSP;      //!< Current DSP in fDSPs.
+               AliBusPatch* fCurrentBusPatch;  //!< Current bus patch in fBusPatches.
+               Bool_t* fCurrentParityOkFlag;  //!< Current parity flag to be set in fParityOk.
+               UInt_t fParityErrors;   //!< Number of parity errors found in DDL.
+               UInt_t fGlitchErrors;   //!< Number of glitch errors found in DDL.
+               UInt_t fPaddingErrors;  //!< Number of padding errors found in DDL.
+               Bool_t fWarnings;       //!< Flag indicating if we should generate a warning for errors.
        };
        
        AliMUONTrackerDDLDecoder<AliDecoderEventHandler> fDecoder;  //!< The decoder for the DDL payload.
        Int_t fDDL;         //!< The current DDL number being handled.
-       UInt_t fCurrentChannel;  //!< The current channel to return by Next().
        Int_t fBufferSize;  //!< This is the buffer size in bytes of fBuffer.
        UChar_t* fBuffer;   //!< This is the buffer in which we store the DDL payload read from AliRawReader.
+       const AliBusPatch* fCurrentBusPatch;  //!< The current data word to return by Next().
+       const UInt_t* fCurrentData;  //!< The current data word to return by Next().
+       const UInt_t* fEndOfData;  //!< The last data word in the current bus patch.
        Bool_t fHadError;   //!< Flag indicating if there was a decoding error or not.
+       Bool_t fDone;       //!< Flag indicating if the iteration is done or not.
 
        ClassDef(AliMUONRawStreamTrackerHP, 0) // High performance decoder for reading MUON raw digits from tracking chamber DDL data.
 };
 
 #endif  // ALIMUONRAWSTREAMTRACKERHP_H
+
index 8ccf972..b82d0e7 100644 (file)
@@ -170,6 +170,8 @@ private:
        UInt_t fMaxBusPatches; ///< Maximum number of bus patch structures allowed in a DDL stream.
        EventHandler fHandler; ///< The event handler which deals with parsing events.
 
+       void DecodeBuffer(const UChar_t* start, const UChar_t* end);
+       
        bool DecodeBlockData(
                        const AliMUONBlockHeaderStruct* blockHeader,
                        const UChar_t* start, const UChar_t* end
@@ -380,12 +382,34 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t b
        fHadError = false;
        
        // We are basically implementing something like a recursive decent parser.
-       // So start by marking the current buffer position and end of buffer.
-       const UChar_t* current = reinterpret_cast<const UChar_t*>(buffer);
-       const UChar_t* end = current + bufferSize;
+       // So start by marking the start of buffer position and end of buffer.
+       const UChar_t* start = reinterpret_cast<const UChar_t*>(buffer);
+       const UChar_t* end = start + bufferSize;
        
-       // Signal a new buffer event.
        fHandler.OnNewBuffer(buffer, bufferSize);
+       DecodeBuffer(start, end);
+       fHandler.OnEndOfBuffer(buffer, bufferSize);
+       return not fHadError;
+}
+
+
+template <class EventHandler>
+void AliMUONTrackerDDLDecoder<EventHandler>::DecodeBuffer(
+               const UChar_t* start, const UChar_t* end
+       )
+{
+       /// This method decodes the buffer's payload data. It unpacks the block
+       /// structures contained inside and then for each block it calls the
+       /// OnNewBlock method for the event handler to signal the start of each new
+       /// block structure. OnEndOfBlock is called once each block is processed.
+       /// \param start  This is the pointer to the start of the buffer.
+       /// \param end  This is the pointer to the first byte just past the
+       ///             end of the buffer.
+       /// \return If the blocks in the buffer were decoded without errors
+       ///      or we could recover from the errors, then true is returned.
+       ///      False is returned otherwise.
+       
+       const UChar_t* current = start;
 
        UInt_t blockCount = 0; // Indicates the number of blocks decoded.
        while (current < end)
@@ -408,7 +432,8 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t b
                                fHandler.OnError(EventHandler::kBufferTooBig, blockHeader);
                        else
                                fHandler.OnError(EventHandler::kNoBlockHeader, blockHeader);
-                       return false;
+                       fHadError = true;
+                       return;
                }
                
                // The header fits the buffer so we can mark the data start and
@@ -436,7 +461,8 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t b
                                // expected, so the remaining data must be rubbish.
                                // Don't even bother trying to recover the data.
                                fHandler.OnError(EventHandler::kBufferTooBig, blockHeader);
-                               return false;
+                               fHadError = true;
+                               return;
                        }
                        if (blockHeader->fDataKey != fgkBlockDataKey)
                                fHandler.OnError(EventHandler::kBadBlockKey, &blockHeader->fDataKey);
@@ -448,12 +474,10 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t b
                                fHandler.OnError(EventHandler::kBlockLengthMismatch, blockHeader);
                        
                        // Stop the decoding if so requested by the user, otherwise
-                       // remember about the error so that we return false from this
-                       // routine and continue decoding.
-                       if (fExitOnError)
-                               return false;
-                       else
-                               fHadError = true;
+                       // remember about the error so that we return false from the
+                       // Decode() method and continue decoding.
+                       fHadError = true;
+                       if (fExitOnError) return;
                        
                        // Try to recover from the corrupt header.
                        RecoverResult result = TryRecoverStruct(
@@ -463,7 +487,7 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t b
                                );
                        if (result == kContinueToNextStruct)
                                continue; // Try the next block at 'current'.
-                       if (result == kRecoverFailed) return false;
+                       if (result == kRecoverFailed) return;
                }
                
                // At this point we certainly have a valid block header, so we
@@ -476,20 +500,25 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t b
                        // In this case we stop the decoding because clearly
                        // something is seriously wrong with the data if we are
                        // getting more blocks than expected.
-                       return false;
+                       fHadError = true;
+                       return;
                }
                
                fHandler.OnNewBlock(blockHeader, dataStart);
-               if (DecodeBlockData(blockHeader, dataStart, dataEnd)) continue;
-               
-               // At this point we had a problem decoding the block structure's
-               // data. Thus we should stop further decoding if so requested by
-               // the user. Note the fHadError flag is already marked inside
-               // DecodeBlockData.
-               if (fExitOnError) return false;
+               if (not DecodeBlockData(blockHeader, dataStart, dataEnd))
+               {
+                       // At this point we had a problem decoding the block structure's
+                       // data. Thus we should stop further decoding if so requested by
+                       // the user. Note the fHadError flag is already marked inside
+                       // DecodeBlockData.
+                       if (fExitOnError)
+                       {
+                               fHandler.OnEndOfBlock(blockHeader, dataStart);
+                               return;
+                       }
+               }
+               fHandler.OnEndOfBlock(blockHeader, dataStart);
        }
-       
-       return not fHadError;
 }
 
 
@@ -607,7 +636,11 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::DecodeBlockData(
                        // the next event.
                        fHandler.OnError(EventHandler::kGlitchFound, &dspHeader->fErrorWord);
                        fHadError = true;
-                       if (fExitOnError) return false;
+                       if (fExitOnError)
+                       {
+                               fHandler.OnEndOfDSP(dspHeader, dataStart);
+                               return false;
+                       }
                        
                        // Try recover by finding the very next DSP and continue
                        // decoding from there. Note: to achieve all we have to do
@@ -629,17 +662,27 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::DecodeBlockData(
                        {
                                fHandler.OnError(EventHandler::kBadPaddingWord, padWord);
                                fHadError = true;
-                               if (fExitOnError) return false;
+                               if (fExitOnError)
+                               {
+                                       fHandler.OnEndOfDSP(dspHeader, dataStart);
+                                       return false;
+                               }
                        }
                }
                
-               if (DecodeDSPData(dataStart, dataEnd)) continue;
-               
-               // At this point we had a problem decoding the DSP structure's
-               // data, thus we should stop further decoding if so requested by
-               // the user. Note the fHadError flag is already marked inside
-               // DecodeDSPData.
-               if (fExitOnError) return false;
+               if (not DecodeDSPData(dataStart, dataEnd))
+               {
+                       // At this point we had a problem decoding the DSP structure's
+                       // data, thus we should stop further decoding if so requested by
+                       // the user. Note the fHadError flag is already marked inside
+                       // DecodeDSPData.
+                       if (fExitOnError)
+                       {
+                               fHandler.OnEndOfDSP(dspHeader, dataStart);
+                               return false;
+                       }
+               }
+               fHandler.OnEndOfDSP(dspHeader, dataStart);
        }
        
        return true;
@@ -749,13 +792,19 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::DecodeDSPData(
                }
                
                fHandler.OnNewBusPatch(busPatchHeader, dataStart);
-               if (DecodeBusPatchData(dataStart, dataEnd)) continue;
-               
-               // At this point we had a problem decoding the bus patch data,
-               // thus we should stop further decoding if so requested by the
-               // user. Note the fHadError flag is already marked inside
-               // DecodeBusPatchData.
-               if (fExitOnError) return false;
+               if (not DecodeBusPatchData(dataStart, dataEnd))
+               {
+                       // At this point we had a problem decoding the bus patch data,
+                       // thus we should stop further decoding if so requested by the
+                       // user. Note the fHadError flag is already marked inside
+                       // DecodeBusPatchData.
+                       if (fExitOnError)
+                       {
+                               fHandler.OnEndOfBusPatch(busPatchHeader, dataStart);
+                               return false;
+                       }
+               }
+               fHandler.OnEndOfBusPatch(busPatchHeader, dataStart);
        }
        
        return true;
@@ -793,7 +842,7 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::DecodeBusPatchData(
        {
                if (ParityIsOk(*data))
                {
-                       fHandler.OnData(*data);
+                       fHandler.OnData(*data, false);
                }
                else
                {
@@ -804,7 +853,7 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::DecodeBusPatchData(
                        if (fExitOnError) return false;
                        
                        if (fSendDataOnParityError)
-                               fHandler.OnData(*data);
+                               fHandler.OnData(*data, true);
                }
        }
        
index 6608f83..1c9cea7 100644 (file)
@@ -97,7 +97,7 @@ class AliMUONTrackerDDLDecoderEventHandler
 public:
 
        /// The only reason for a virtual destructor is to make -Weffc++ shutup.
-       /// This should not really be here.
+       /// This should not really be here since we do not need or use virtual methods.
        virtual ~AliMUONTrackerDDLDecoderEventHandler() {}
 
        /// All the possible error codes for the parsing.
@@ -141,6 +141,8 @@ public:
        /// - param UInt_t The size in bytes of the memory buffer.
        void OnNewBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/) {}
        
+       void OnEndOfBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/) {}
+       
        /// OnNewBlock is called whenever a new block header is found in the payload.
        /// The default behaviour of this method is to do nothing.
        /// - param const AliMUONBlockHeaderStruct* This is a pointer to the block header as found in the
@@ -151,6 +153,8 @@ public:
        /// because no memory copying is required.
        void OnNewBlock(const AliMUONBlockHeaderStruct* /*header*/, const void* /*data*/) {}
        
+       void OnEndOfBlock(const AliMUONBlockHeaderStruct* /*header*/, const void* /*data*/) {}
+       
        /// OnNewDSP is called whenever a new DSP header is found in the payload.
        /// Every DSP header recevied by a call to OnNewDSP is associated to the
        /// block header received in the most recent call to OnNewBlock.
@@ -163,6 +167,8 @@ public:
        /// because no memory copying is required.
        void OnNewDSP(const AliMUONDSPHeaderStruct* /*header*/, const void* /*data*/) {}
        
+       void OnEndOfDSP(const AliMUONDSPHeaderStruct* /*header*/, const void* /*data*/) {}
+       
        /// OnNewBusPatch is called whenever a new bus patch header is found in
        /// the payload. Every bus patch recevied by a call to OnNewBusPatch is
        /// associated to the DSP header received in the most recent call to OnNewDSP.
@@ -176,12 +182,17 @@ public:
        /// because no memory copying is required.
        void OnNewBusPatch(const AliMUONBusPatchHeaderStruct* /*header*/, const void* /*data*/) {}
        
+       void OnEndOfBusPatch(const AliMUONBusPatchHeaderStruct* /*header*/, const void* /*data*/) {}
+       
        /// OnData is called for every raw data word found within a bus patch.
        /// Every data ward recevied by a call to OnData is associated to the bus patch
        /// header received in the most recent call to OnNewBusPatch.
        /// The default behaviour of this method is to do nothing.
        /// - param UInt_t  This is the raw data word as found within the bus patch payload.
-       void OnData(UInt_t /*data*/) {}
+       /// - param bool  Flag indicating if the raw data word had a parity error.
+       ///       This will always be set to false if fSendDataOnParityError in the
+       ///       AliMUONTrackerDDLDecoder class was set to true.
+       void OnData(UInt_t /*data*/, bool /*parityError*/) {}
        
        /// Whenever a parsing error of the DDL payload is encountered because of
        /// corruption of the raw data (eg. bit flips) the OnError method is called
index a1997d0..24b4a1e 100644 (file)
@@ -33,39 +33,6 @@ public:
                                UShort_t& manuId, UChar_t& manuChannel,
                                UShort_t& adc) = 0;
        
-       /// Class used in the following Next() method to return blocks of decoded
-       /// channel data. This is better because we generate a lot fewer method calls.
-       class AliChannelInfo
-       {
-       public:
-               /// Default constructor.
-               AliChannelInfo(Int_t busPatchId = 0, UShort_t manuId = 0, UChar_t channelId = 0, UShort_t adc = 0) :
-                       fBusPatchId(busPatchId), fManuId(manuId), fChannelId(channelId), fADC(adc)
-               {}
-               
-               /// Returns the bus patch ID.
-               Int_t BusPatchId() const { return fBusPatchId; }
-               /// Returns the MANU ID.
-               UShort_t ManuId() const { return fManuId; }
-               /// Returns the channel ID.
-               UShort_t ChannelId() const { return fChannelId; }
-               /// ADC signal.
-               UShort_t ADC() const { return fADC; }
-       
-       private:
-               Int_t fBusPatchId;  //!< The bus patch ID for this channel.
-               UShort_t fManuId;   //!< MANU ID.
-               UChar_t fChannelId; //!< MANU channel ID.
-               UShort_t fADC;      //!< ADC signal.
-       };
-       
-       /// Returns the next batch of decoded channel data.
-       /// [out] \param channels  This is filled with the pointer to the array
-       ///                        containing the channel information.
-       /// \return The number of elements in the 'channels' array is returned.
-       ///     Zero is returned if there are no more digits to be fetched.
-       virtual UInt_t Next(const AliChannelInfo*& channels) = 0;
-       
        /// Return maximum number of DDLs
        static Int_t GetMaxDDL() { return fgkMaxDDL; };
        
index 36e2ae7..c0f1a90 100644 (file)
 // Macro for reading tracker raw data
 // Ch. Finck, Subatech Febuary
 //
+// Added example routines to show how to use the interface of the high
+// performance decoder AliMUONRawStreamTrackerHP.
+//   Artur Szostak <artursz@iafrica.com>
+//
 
 #if !defined(__CINT__) || defined(__MAKECINT__)
 
@@ -27,6 +31,7 @@
 
 // MUON includes
 #include "AliMUONRawStreamTracker.h"
+#include "AliMUONRawStreamTrackerHP.h"
 #include "AliMUONDspHeader.h"
 #include "AliMUONBlockHeader.h"
 #include "AliMUONBusStruct.h"
@@ -160,7 +165,285 @@ void MUONRawStreamTrackerExpert(TString fileName = "./", Int_t maxEvent = 1000,
   timer.Print();
 }
 
-void MUONRawStreamTrackerSimple(TString fileName, Int_t maxEvent)
+
+void MUONRawStreamTrackerHPExpert(TString fileName = "./", Int_t maxEvent = 1000,  
+                                Int_t minDDL = 0, Int_t maxDDL = 19)
+{
+  /// This routine shows how to use the high performance decoder's expert interface.
+  
+  TStopwatch timer;
+  timer.Start(kTRUE);
+  
+  AliRawReader* rawReader = 0x0;
+  
+  // check extention to choose the rawdata file format
+  if (fileName.EndsWith("/")) {
+    rawReader = new AliRawReaderFile(fileName); // DDL files
+  } else if (fileName.EndsWith(".root")) {
+    rawReader = new AliRawReaderRoot(fileName);
+  } else if (!fileName.IsNull()) {
+    rawReader = new AliRawReaderDate(fileName); // DATE file
+  }
+  
+  // raw stream
+  AliMUONRawStreamTrackerHP* rawStream  = new AliMUONRawStreamTrackerHP(rawReader);
+  
+  // light weight interfaces to headers
+  const AliMUONRawStreamTrackerHP::AliBlockHeader*      blkHeader  = 0x0;
+  const AliMUONRawStreamTrackerHP::AliDspHeader*        dspHeader  = 0x0;
+  const AliMUONRawStreamTrackerHP::AliBusPatch*         busStruct  = 0x0;
+  
+  //   Loop over events  
+  Int_t iEvent = 0;
+  Int_t dataSize;
+  
+  while (rawReader->NextEvent()) {
+    
+    if (iEvent == maxEvent)
+      break;
+    
+    printf("Event %d\n",iEvent++);
+    
+    // read DDL while < 20 DDL
+    while(rawStream->NextDDL()) {
+      
+      if (rawStream->GetDDL() < minDDL || rawStream->GetDDL() > maxDDL)
+        continue;
+      
+      printf("\niDDL %d\n", rawStream->GetDDL());
+      
+      // loop over block structure
+      Int_t nBlock = rawStream->GetBlockCount();
+      for(Int_t iBlock = 0; iBlock < nBlock ;iBlock++){
+        
+        blkHeader = rawStream->GetBlockHeader(iBlock);
+        printf("Block %d Total length %d\n",iBlock,blkHeader->GetTotalLength());
+       
+        // loop over DSP structure
+        Int_t nDsp = rawStream->GetDspCount(iBlock);
+        for(Int_t iDsp = 0; iDsp < nDsp ;iDsp++){   //DSP loop
+          
+          dspHeader =  blkHeader->GetDspHeader(iDsp);
+          printf("Dsp %d length %d error word %d\n",iDsp,dspHeader->GetTotalLength(), dspHeader->GetErrorWord());
+          
+          // loop over BusPatch structure
+          Int_t nBusPatch = rawStream->GetBusPatchCount(iBlock, iDsp);
+          for(Int_t iBusPatch = 0; iBusPatch < nBusPatch; iBusPatch++) {  
+            
+            busStruct = dspHeader->GetBusPatch(iBusPatch);
+            
+            // loop over data
+            dataSize = busStruct->GetLength();
+            for (Int_t iData = 0; iData < dataSize; iData++) {
+              
+              Int_t  manuId    = busStruct->GetManuId(iData);
+              Int_t  channelId = busStruct->GetChannelId(iData);
+              Int_t  charge    = busStruct->GetCharge(iData);
+              printf("buspatch %5d manuI %4d channel %3d charge %4d\n", 
+                     busStruct->GetBusPatchId(),
+                     manuId, 
+                     channelId, charge);
+            } // iData
+          } // iBusPatch
+        } // iDsp
+      } // iBlock
+    } // NextDDL
+  }// NextEvent
+  
+  delete rawReader;
+  delete rawStream;
+  timer.Print();
+}
+
+
+void MUONRawStreamTrackerHPExpert2(TString fileName = "./", Int_t maxEvent = 1000,  
+                                Int_t minDDL = 0, Int_t maxDDL = 19)
+{
+  /// This routine shows an alternate way to iterate over the DDL structures
+  /// compared to MUONRawStreamTrackerHPExpert().
+  
+  TStopwatch timer;
+  timer.Start(kTRUE);
+  
+  AliRawReader* rawReader = 0x0;
+  
+  // check extention to choose the rawdata file format
+  if (fileName.EndsWith("/")) {
+    rawReader = new AliRawReaderFile(fileName); // DDL files
+  } else if (fileName.EndsWith(".root")) {
+    rawReader = new AliRawReaderRoot(fileName);
+  } else if (!fileName.IsNull()) {
+    rawReader = new AliRawReaderDate(fileName); // DATE file
+  }
+  
+  // raw stream
+  AliMUONRawStreamTrackerHP* rawStream  = new AliMUONRawStreamTrackerHP(rawReader);
+  
+  // light weight interfaces to headers
+  const AliMUONRawStreamTrackerHP::AliBlockHeader*      blkHeader  = 0x0;
+  const AliMUONRawStreamTrackerHP::AliDspHeader*        dspHeader  = 0x0;
+  const AliMUONRawStreamTrackerHP::AliBusPatch*         busStruct  = 0x0;
+  
+  //   Loop over events  
+  Int_t iEvent = 0;
+  Int_t dataSize;
+  
+  while (rawReader->NextEvent()) {
+    
+    if (iEvent == maxEvent)
+      break;
+    
+    printf("Event %d\n",iEvent++);
+    
+    // read DDL while < 20 DDL
+    while(rawStream->NextDDL()) {
+      
+      if (rawStream->GetDDL() < minDDL || rawStream->GetDDL() > maxDDL)
+        continue;
+      
+      printf("\niDDL %d\n", rawStream->GetDDL());
+      
+      // loop over block structure
+      Int_t nBlock = rawStream->GetBlockCount();
+      for(Int_t iBlock = 0; iBlock < nBlock ;iBlock++){
+        
+        blkHeader = rawStream->GetBlockHeader(iBlock);
+        printf("Block %d Total length %d\n",iBlock,blkHeader->GetTotalLength());
+       
+        // loop over DSP structure
+        Int_t nDsp = rawStream->GetDspCount(iBlock);
+        for(Int_t iDsp = 0; iDsp < nDsp ;iDsp++){   //DSP loop
+          
+          dspHeader =  rawStream->GetDspHeader(iBlock, iDsp);
+          printf("Dsp %d length %d error word %d\n",iDsp,dspHeader->GetTotalLength(), dspHeader->GetErrorWord());
+          
+          // loop over BusPatch structure
+          Int_t nBusPatch = rawStream->GetBusPatchCount(iBlock, iDsp);
+          for(Int_t iBusPatch = 0; iBusPatch < nBusPatch; iBusPatch++) {  
+            
+            busStruct = rawStream->GetBusPatch(iBlock, iDsp, iBusPatch);
+            
+            // loop over data
+            dataSize = busStruct->GetLength();
+            for (Int_t iData = 0; iData < dataSize; iData++) {
+              
+              Int_t  manuId    = busStruct->GetManuId(iData);
+              Int_t  channelId = busStruct->GetChannelId(iData);
+              Int_t  charge    = busStruct->GetCharge(iData);
+              printf("buspatch %5d manuI %4d channel %3d charge %4d\n", 
+                     busStruct->GetBusPatchId(),
+                     manuId, 
+                     channelId, charge);
+            } // iData
+          } // iBusPatch
+        } // iDsp
+      } // iBlock
+    } // NextDDL
+  }// NextEvent
+  
+  delete rawReader;
+  delete rawStream;
+  timer.Print();
+}
+
+
+void MUONRawStreamTrackerHPExpert3(TString fileName = "./", Int_t maxEvent = 1000,  
+                                Int_t minDDL = 0, Int_t maxDDL = 19)
+{
+  /// This routine shows yet another alternate way to iterate over the DDL
+  /// structures compared to MUONRawStreamTrackerHPExpert().
+  
+  TStopwatch timer;
+  timer.Start(kTRUE);
+  
+  AliRawReader* rawReader = 0x0;
+  
+  // check extention to choose the rawdata file format
+  if (fileName.EndsWith("/")) {
+    rawReader = new AliRawReaderFile(fileName); // DDL files
+  } else if (fileName.EndsWith(".root")) {
+    rawReader = new AliRawReaderRoot(fileName);
+  } else if (!fileName.IsNull()) {
+    rawReader = new AliRawReaderDate(fileName); // DATE file
+  }
+  
+  // raw stream
+  AliMUONRawStreamTrackerHP* rawStream  = new AliMUONRawStreamTrackerHP(rawReader);
+  
+  // light weight interfaces to headers
+  const AliMUONRawStreamTrackerHP::AliBlockHeader*      blkHeader  = 0x0;
+  const AliMUONRawStreamTrackerHP::AliDspHeader*        dspHeader  = 0x0;
+  const AliMUONRawStreamTrackerHP::AliBusPatch*         busStruct  = 0x0;
+  
+  //   Loop over events  
+  Int_t iEvent = 0;
+  Int_t dataSize;
+  
+  while (rawReader->NextEvent()) {
+    
+    if (iEvent == maxEvent)
+      break;
+    
+    printf("Event %d\n",iEvent++);
+    
+    // read DDL while < 20 DDL
+    while(rawStream->NextDDL()) {
+      
+      if (rawStream->GetDDL() < minDDL || rawStream->GetDDL() > maxDDL)
+        continue;
+      
+      printf("\niDDL %d\n", rawStream->GetDDL());
+      
+      // loop over block structure
+      Int_t iBlock = 0;
+      blkHeader = rawStream->GetFirstBlockHeader();
+      while (blkHeader != NULL)
+      {
+        printf("Block %d Total length %d\n",iBlock,blkHeader->GetTotalLength());
+       
+        // loop over DSP structure
+        Int_t iDsp = 0;
+        dspHeader = blkHeader->GetFirstDspHeader();
+        while (dspHeader != NULL)
+        {
+          printf("Dsp %d length %d error word %d\n",iDsp,dspHeader->GetTotalLength(), dspHeader->GetErrorWord());
+          
+          // loop over BusPatch structure
+          Int_t iBusPatch = 0;
+          busStruct = dspHeader->GetFirstBusPatch();
+          while (busStruct != NULL)
+          {
+            // loop over data
+            dataSize = busStruct->GetLength();
+            for (Int_t iData = 0; iData < dataSize; iData++) {
+              
+              Int_t  manuId    = busStruct->GetManuId(iData);
+              Int_t  channelId = busStruct->GetChannelId(iData);
+              Int_t  charge    = busStruct->GetCharge(iData);
+              printf("buspatch %5d manuI %4d channel %3d charge %4d\n", 
+                     busStruct->GetBusPatchId(),
+                     manuId, 
+                     channelId, charge);
+            } // iData
+            busStruct = busStruct->Next();
+            iBusPatch++;
+          } // iBusPatch
+          dspHeader = dspHeader->Next();
+          iDsp++;
+        } // iDsp
+        blkHeader = blkHeader->Next();
+        iBlock++;
+      } // iBlock
+    } // NextDDL
+  }// NextEvent
+  
+  delete rawReader;
+  delete rawStream;
+  timer.Print();
+}
+
+
+void MUONRawStreamTrackerSimple(TString fileName = "./", Int_t maxEvent = 1000)
 {
   /// Reads the raw data in fileName, using a simplified interface (iterator
   /// over pads).
@@ -209,3 +492,106 @@ void MUONRawStreamTrackerSimple(TString fileName, Int_t maxEvent)
   timer.Print();
 }
 
+
+void MUONRawStreamTrackerHPSimple(TString fileName = "./", Int_t maxEvent = 1000)
+{
+  /// This routine shows how to use the high performance decoder's simple interface.
+
+  TStopwatch timer;
+  timer.Start(kTRUE);
+  
+  AliRawReader* rawReader = 0x0;
+  
+  // check extention to choose the rawdata file format
+  if (fileName.EndsWith("/")) {
+    rawReader = new AliRawReaderFile(fileName); // DDL files
+  } else if (fileName.EndsWith(".root")) {
+    rawReader = new AliRawReaderRoot(fileName);
+  } else if (!fileName.IsNull()) {
+    rawReader = new AliRawReaderDate(fileName); // DATE file
+  }
+  
+  // raw stream
+  AliMUONRawStreamTrackerHP* rawStream  = new AliMUONRawStreamTrackerHP(rawReader);    
+  
+  //   Loop over events  
+  Int_t iEvent = 0;
+  
+  while (rawReader->NextEvent()) {
+    
+    if (iEvent == maxEvent)
+      break;
+    
+    printf("Event %d\n",iEvent++);
+    
+    Int_t busPatch;
+    UShort_t manuId, adc;
+    UChar_t manuChannel;
+    
+    rawStream->First();
+    
+    while ( rawStream->Next(busPatch,manuId,manuChannel,adc) )
+    {      
+      printf("buspatch %5d manuI %4d channel %3d charge %4d\n", 
+             busPatch,manuId,manuChannel, adc);
+    }
+  }
+  
+  delete rawReader;
+  delete rawStream;
+  timer.Print();
+}
+
+
+void MUONRawStreamTrackerHPSimple2(TString fileName = "./", Int_t maxEvent = 1000)
+{
+  /// This routine is an alternative to MUONRawStreamTrackerHPSimple() which is even faster.
+
+  TStopwatch timer;
+  timer.Start(kTRUE);
+  
+  AliRawReader* rawReader = 0x0;
+  
+  // check extention to choose the rawdata file format
+  if (fileName.EndsWith("/")) {
+    rawReader = new AliRawReaderFile(fileName); // DDL files
+  } else if (fileName.EndsWith(".root")) {
+    rawReader = new AliRawReaderRoot(fileName);
+  } else if (!fileName.IsNull()) {
+    rawReader = new AliRawReaderDate(fileName); // DATE file
+  }
+  
+  // raw stream
+  AliMUONRawStreamTrackerHP* rawStream  = new AliMUONRawStreamTrackerHP(rawReader);    
+  
+  //   Loop over events  
+  Int_t iEvent = 0;
+  
+  while (rawReader->NextEvent()) {
+    
+    if (iEvent == maxEvent)
+      break;
+    
+    printf("Event %d\n",iEvent++);
+    
+    UShort_t manuId, adc;
+    UChar_t manuChannel;
+    
+    rawStream->First();
+    const AliMUONRawStreamTrackerHP::AliBusPatch* buspatch = NULL;
+    while ((buspatch = rawStream->Next()) != NULL)
+    {
+      for (UInt_t i = 0; i < buspatch->GetDataCount(); i++)
+      {
+        buspatch->GetData(i, manuId, manuChannel, adc);
+        printf("buspatch %5d manuI %4d channel %3d charge %4d\n", 
+               buspatch->GetBusPatchId(), manuId, manuChannel, adc);
+      }
+    }
+  }
+  
+  delete rawReader;
+  delete rawStream;
+  timer.Print();
+}
+
index 7d2de43..3411e32 100644 (file)
@@ -22,6 +22,9 @@
 #pragma link C++ class AliMUONVRawStreamTracker+;
 #pragma link C++ class AliMUONRawStreamTracker+;
 #pragma link C++ class AliMUONRawStreamTrackerHP+;
+#pragma link C++ class AliMUONRawStreamTrackerHP::AliBlockHeader+;
+#pragma link C++ class AliMUONRawStreamTrackerHP::AliDspHeader+;
+#pragma link C++ class AliMUONRawStreamTrackerHP::AliBusPatch+;
 #pragma link C++ class AliMUONRawStreamTrigger+;
 #pragma link C++ class AliMUONRawStream+;