]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - MUON/AliMUONRawStreamTrackerHP.cxx
Extracting Branch and Revision from Git.
[u/mrichter/AliRoot.git] / MUON / AliMUONRawStreamTrackerHP.cxx
index 909fe1cd8988b4da39da9c234a2c1dd2d014e585..73fa28b13a529f9b9ff6fd3ff53833f51e8fbed6 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 "AliMUONRawStreamTrackerHP.h"
+#include "AliMUONTrackerDDLDecoder.h"
+#include "AliMUONDspHeader.h"
+#include "AliMUONBlockHeader.h"
+#include "AliMUONBusStruct.h"
+#include "AliMUONDDLTracker.h"
+#include "AliMUONLogger.h"
 #include "AliRawReader.h"
 #include "AliLog.h"
+#include "AliDAQ.h"
 #include <cassert>
+#include <iostream>
+using std::cout;
+using std::endl;
+using std::hex;
+using std::dec;
 
 /// \cond CLASSIMP
 ClassImp(AliMUONRawStreamTrackerHP)
 /// \endcond
 
+const Int_t AliMUONRawStreamTrackerHP::fgkMaxDDL = 20;
 
 AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() :
-       AliMUONVRawStreamTracker(),
+       TObject(),
+       fRawReader(NULL),
+       fLogger(NULL),
+       fDetailLevel(kMediumErrorDetail),
+       fEnableMUONErrorLogger(kFALSE),
+       fEnableRawReaderErrorLogger(kFALSE),
+       fWarnings(kTRUE),
        fDecoder(),
        fDDL(0),
-       fCurrentChannel(0),
        fBufferSize(8192),
        fBuffer(new UChar_t[8192]),
-       fHadError(kFALSE)
+       fkCurrentBusPatch(NULL),
+       fkCurrentData(NULL),
+       fkEndOfData(NULL),
+       fHadError(kFALSE),
+       fDone(kFALSE),
+       fDDLObject(NULL),
+       fTotalNumberOfGlitchErrors(0),
+       fTotalNumberOfParityErrors(0),
+       fTotalNumberOfPaddingErrors(0),
+       fTotalNumberOfTokenLostErrors(0)
 {
        ///
        /// 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);
 }
 
 
 AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP(AliRawReader* rawReader) :
-       AliMUONVRawStreamTracker(rawReader),
+       TObject(),
+       fRawReader(rawReader),
+       fLogger(NULL),
+       fDetailLevel(kMediumErrorDetail),
+       fEnableMUONErrorLogger(kFALSE),
+       fEnableRawReaderErrorLogger(kFALSE),
+       fWarnings(kTRUE),
        fDecoder(),
        fDDL(0),
-       fCurrentChannel(0),
        fBufferSize(8192),
        fBuffer(new UChar_t[8192]),
-       fHadError(kFALSE)
+       fkCurrentBusPatch(NULL),
+       fkCurrentData(NULL),
+       fkEndOfData(NULL),
+       fHadError(kFALSE),
+       fDone(kFALSE),
+       fDDLObject(NULL),
+       fTotalNumberOfGlitchErrors(0),
+       fTotalNumberOfParityErrors(0),
+       fTotalNumberOfPaddingErrors(0),
+       fTotalNumberOfTokenLostErrors(0)
 {
        ///
        /// 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);
 }
 
@@ -91,6 +160,10 @@ AliMUONRawStreamTrackerHP::~AliMUONRawStreamTrackerHP()
        {
                delete [] fBuffer;
        }
+       if (fDDLObject != NULL)
+       {
+               delete fDDLObject;
+       }
 }
 
 
@@ -102,7 +175,12 @@ void AliMUONRawStreamTrackerHP::First()
        assert( GetReader() != NULL );
        
        fDDL = 0;
+       fDone = kFALSE;
        NextDDL();
+       fTotalNumberOfGlitchErrors = 0;
+       fTotalNumberOfPaddingErrors = 0;
+       fTotalNumberOfParityErrors = 0;
+       fTotalNumberOfTokenLostErrors = 0;
 }
 
 
@@ -114,9 +192,20 @@ Bool_t AliMUONRawStreamTrackerHP::NextDDL()
 
        assert( GetReader() != NULL );
        
-       if (IsDone()) return kFALSE;
+       // The temporary object if generated in GetDDLTracker, is now stale,
+       // so delete it.
+       if (fDDLObject != NULL)
+       {
+               delete fDDLObject;
+               fDDLObject = NULL;
+       }
        
-       do
+       // Better to reset these pointers.
+       fkCurrentBusPatch = NULL;
+       fkCurrentData = NULL;
+       fkEndOfData = NULL;
+       
+       while (fDDL < GetMaxDDL())
        {
                GetReader()->Reset();
                GetReader()->Select("MUONTRK", fDDL, fDDL);  // Select the DDL file to be read.
@@ -124,8 +213,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 exit.
+       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
@@ -157,25 +258,47 @@ Bool_t AliMUONRawStreamTrackerHP::NextDDL()
        }
        
 #ifndef R__BYTESWAP
-       Swap(fBuffer, dataSize); // Swap needed for mac power pc.
+       Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc.
 #endif
        
+       fDDL++; // Remember to increment index to next DDL before the calls to
+               // fDecoder.Decode since the callback methods of the decoder will
+               // use AliMUONRawStreamTrackerHP::GetDDL()
+       
        bool result = false;
        try
        {
                // 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);
+               fTotalNumberOfGlitchErrors += fDecoder.GetHandler().GlitchErrorCount();
+               fTotalNumberOfParityErrors += fDecoder.GetHandler().ParityErrorCount();
+               fTotalNumberOfPaddingErrors += fDecoder.GetHandler().PaddingErrorCount();
+               fTotalNumberOfTokenLostErrors += fDecoder.GetHandler().TokenLostCount();
        }
        catch (const std::bad_alloc&)
        {
                AliError("Could not allocate more buffer space. Cannot decode DDL.");
                return kFALSE;
        }
-       
-       fCurrentChannel = 0;
-       fDDL++; // Remember to increment index to next DDL.
-       return result;
+
+       // Update the current bus patch pointers.
+       fkCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch();
+       if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
+       {
+               fkCurrentData = fkCurrentBusPatch->GetData();
+               fkEndOfData = fkCurrentData + fkCurrentBusPatch->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.
+               fkCurrentData = fkEndOfData = NULL;
+       }
+
+       return kTRUE;
 }
 
 
@@ -184,90 +307,259 @@ 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;
 }
 
 
-Bool_t AliMUONRawStreamTrackerHP::Next(
-               Int_t& busPatchId, UShort_t& manuId, UChar_t& manuChannel,
-               UShort_t& adc
-       )
+Bool_t AliMUONRawStreamTrackerHP::Next(Int_t& busPatchId, 
+                                       UShort_t& manuId, 
+                                       UChar_t& manuChannel,
+                                       UShort_t& adc, 
+                                       Bool_t skipParityErrors)
 {
        /// Advance one step in the iteration. Returns false if finished.
        /// [out] \param busPatchId  This is filled with the bus patch ID of the digit.
        /// [out] \param manuId      This is filled with the MANU ID of the digit.
        /// [out] \param manuChannel This is filled with the MANU channel ID of the digit.
        /// [out] \param adc         This is filled with the ADC signal value of the digit.
+       /// [in] \param skipParityErrors If this is kTRUE, we'll skip the buspatches that
+       ///                              have some parity errors
        /// \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())
+       if (fkCurrentData == NULL) return kFALSE;
+       
+retry:
+       // Check if we still have data to be returned for the current bus patch.
+       if (fkCurrentData != fkEndOfData)
        {
-               const AliChannelInfo& channel = fDecoder.GetHandler().Channels()[fCurrentChannel];
-               busPatchId = channel.BusPatchId();
-               manuId = channel.ManuId();
-               manuChannel = channel.ChannelId();
-               adc = channel.ADC();
-               fCurrentChannel++;
+               busPatchId = fkCurrentBusPatch->GetBusPatchId();
+               AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fkCurrentData, manuId, manuChannel, adc);
+               fkCurrentData++;
                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 (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
                {
-                       if (fCurrentChannel < fDecoder.GetHandler().ChannelCount())
+                       fkCurrentBusPatch++;
+                       if (fkCurrentBusPatch != 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;
+                               fkCurrentData = fkCurrentBusPatch->GetData();
+                               fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount();
+                               if ( skipParityErrors )
+                               {
+                                       Bool_t ok(kTRUE);
+                                       for ( Int_t i = 0; i < fkCurrentBusPatch->GetLength() && ok; ++ i )
+                                       {
+                                               ok = fkCurrentBusPatch->IsParityOk(i);
+                                       }
+                                       if (!ok) fkCurrentData = fkEndOfData;
+                               }
+                               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)
+AliMUONDDLTracker* AliMUONRawStreamTrackerHP::GetDDLTracker() const
 {
-       /// 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.
-       
-       // 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())
+       /// Construct and return a pointer to the DDL payload object.
+       /// \return Pointer to internally constructed AliMUONDDLTracker object.
+       ///         The object is owned by this class and should not be deleted
+       ///         by the caller.
+       ///
+       /// \note This method should not be used just to gain access to the DDL
+       /// payload, unless there is a good reason to have the AliMUONDDLTracker
+       /// object. For example, if you want to modify the data and then save it
+       /// to another DDL stream. Otherwise it can be an order of magnitude
+       /// faster to access the DDL headers and data with the GetBlockHeader,
+       /// GetDspHeader and GetBusPatch methods for example.
+       /// Refer to the MUONRawStreamTracker.C macro to see how to use the fast
+       /// decoder interface optimally.
+       
+       if (fDDLObject != NULL) return fDDLObject;
+       
+       fDDLObject = new AliMUONDDLTracker;
+       for (Int_t iBlock = 0; iBlock < (Int_t)GetBlockCount(); iBlock++)
        {
-               do
+               AliMUONBlockHeader blockHeader;
+               AliMUONDspHeader dspHeader;
+               AliMUONBusStruct busPatch;
+               
+               const AliBlockHeader* bh = GetBlockHeader(iBlock);
+               // Copy block header and add it to the DDL object.
+               memcpy(blockHeader.GetHeader(), bh->GetHeader(), sizeof(AliMUONBlockHeaderStruct));
+               fDDLObject->AddBlkHeader(blockHeader);
+               
+               for (Int_t iDsp = 0; iDsp < (Int_t)bh->GetDspCount(); iDsp++)
                {
-                       if (not NextDDL()) return 0;
+                       const AliDspHeader* dh = bh->GetDspHeader(iDsp);
+                       // Copy DSP header and add it to the DDL object.
+                       memcpy(dspHeader.GetHeader(), dh->GetHeader(), sizeof(AliMUONDSPHeaderStruct));
+                       fDDLObject->AddDspHeader(dspHeader, iBlock);
+                       
+                       const AliBusPatch* bp = dh->GetFirstBusPatch();
+                       while (bp != NULL)
+                       {
+                               // Copy bus patch header, data and add everything into DDL object.
+                               memcpy(busPatch.GetHeader(), bp->GetHeader(), sizeof(AliMUONBusPatchHeaderStruct));
+                               busPatch.SetAlloc(bp->GetLength());
+                               memcpy(busPatch.GetData(), bp->GetData(), bp->GetDataCount()*sizeof(UInt_t));
+                               busPatch.SetBlockId(iBlock);
+                               busPatch.SetDspId(iDsp);
+                               fDDLObject->AddBusPatch(busPatch, iBlock, iDsp);
+                               bp = bp->Next();
+                       }
                }
-               // Make sure to keep going even for empty DDL payloads:
-               while (fDecoder.GetHandler().ChannelCount() == 0);
        }
-       channels = fDecoder.GetHandler().Channels() + fCurrentChannel;
-       return fDecoder.GetHandler().ChannelCount() - fCurrentChannel;
+       
+       return fDDLObject;
+}
+
+
+void AliMUONRawStreamTrackerHP::SetMaxBlock(Int_t blk)
+{
+       /// Set maximum number of blocks per DDL allowed.
+       fDecoder.MaxBlocks( (UInt_t) blk );
+       
+       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)
+       {
+               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;
+       }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 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),
+       fTokenLostErrors(0),
+       fMaxBlocks(),
+       fMaxDsps(),
+       fMaxBusPatches()
 {
-       /// 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 +567,51 @@ 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 [] fChannelBuffer;
+               delete [] fBlocks;
+               fBlocks = NULL;
        }
+       if (fDSPs != NULL)
+       {
+               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 = fBusPatches;
+
+       fMaxBlocks = maxBlocks;
+       fMaxDsps = maxDsps;
+       fMaxBusPatches = maxBusPatches;
 }
 
+
 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer(
                const void* buffer, UInt_t bufferSize
        )
@@ -292,54 +623,65 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer(
 
        // 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;
+       fTokenLostErrors = 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;
+       // 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;
 }
 
 
-void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnData(UInt_t data)
+void AliMUONRawStreamTrackerHP::Swap(UInt_t* buffer, Int_t size) const
 {
-       /// 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).
+       // swap from little to big endian
        
-       assert( fChannelCount < fMaxChannels );
+       typedef struct {
+               UInt_t b1:8; ///< first byte word
+               UInt_t b2:8; ///< second byte word
+               UInt_t b3:8; ///< third byte word
+               UInt_t b4:8; ///< fourth byte word
+       } RawWord;
        
-       UShort_t manuId; UChar_t channelId; UShort_t adc;
-       UnpackADC(data, manuId, channelId, adc);
-       fChannelBuffer[fChannelCount] = AliChannelInfo(fBusPatchId, manuId, channelId, adc);
-       fChannelCount++;
+       RawWord* word, temp;
+       word = (RawWord*) buffer;
+       
+       for (Int_t i = 0; i < size; i++)
+       {
+               temp = *(((RawWord*)buffer)+i);
+               word->b1 = temp.b4;
+               word->b2 = temp.b3;
+               word->b3 = temp.b2;
+               word->b4 = temp.b1;
+               word++;
+       }
 }
 
 
@@ -350,26 +692,213 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError(
        /// This is called by the high performance decoder when a error occurs
        /// when trying to decode the DDL payload. This indicates corruption in
        /// the data. This method converts the error code to a descriptive message
-       /// and log this with the raw reader.
+       /// and logs this with the logger object.
        /// \param error  The error code indicating the problem.
        /// \param location  A pointer to the location within the DDL payload buffer
        ///              being decoded where the problem with the data was found.
-
-       assert( fRawStream != NULL );
-       assert( fRawStream->GetReader() != NULL );
        
-       const char* msg = ErrorCodeToMessage(error);
-       unsigned long pos = (unsigned long)location - (unsigned long)fBufferStart;
+       assert(fRawStream != NULL);
+       
+       const char* message = NULL;
+       UInt_t word = 0;
+       bool logAsMajorError = true;
        
+       // Build the detailed part of the error message if high detail selected.
+       const char* detail = "";
+       if (fRawStream->GetLoggingDetailLevel() == kHighErrorDetail)
+       {
+               bool blockPtrOk = fBlockCount > 0;
+               bool dspPtrOk = blockPtrOk ? fCurrentBlock->GetDspCount() > 0 : false;
+               bool buspatchPtrOk = dspPtrOk ? fCurrentDSP->GetBusPatchCount() > 0 : false;
+               // We subtract 1 from the current numbers of blocks, DSPs
+               // and bus patches to get the iBlock, iDsp and iBus indices.
+               detail = Form(
+                       "At byte %lu in DDL %d, event %d, iBlock %d, iDsp %d [DSP ID: %d (0x%X)],"
+                       " iBus %d [bus patch ID: %d (0x%X)].",
+                       (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader),
+                       AliDAQ::DdlID("MUONTRK", fRawStream->GetDDL()),
+                       fRawStream->GetReader()->GetEventIndex(),
+                       int(fBlockCount)-1,
+                       blockPtrOk ? int(fCurrentBlock->GetDspCount())-1 : -1,
+                       blockPtrOk ? fCurrentBlock->GetDspId() : -1,
+                       blockPtrOk ? fCurrentBlock->GetDspId() : -1,
+                       dspPtrOk ? int(fCurrentDSP->GetBusPatchCount())-1 : -1,
+                       buspatchPtrOk ? fCurrentBusPatch->GetBusPatchId() : -1,
+                       buspatchPtrOk ? fCurrentBusPatch->GetBusPatchId() : -1
+               );
+       }
+       
+       // Build the log message.
        switch (error)
        {
+       case kGlitchFound:
+               fGlitchErrors++;
+               switch (fRawStream->GetLoggingDetailLevel())
+               {
+               case kLowErrorDetail:
+                       message = "Glitch error detected.";
+                       break;
+               case kMediumErrorDetail:
+                       message = Form(
+                               "Glitch error detected in DSP %d (0x%X), skipping event.",
+                               fCurrentBlock->GetDspId(), fCurrentBlock->GetDspId()
+                       );
+                       break;
+               case kHighErrorDetail:
+               default:
+                       message = Form("%s %s", ErrorCodeToMessage(error), detail);
+                       break;
+               }
+               logAsMajorError = true;
+               break;
+
        case kBadPaddingWord:
+               fPaddingErrors++;
+               switch (fRawStream->GetLoggingDetailLevel())
+               {
+               case kLowErrorDetail:
+                       message = "Padding word error detected.";
+                       break;
+               case kMediumErrorDetail:
+                       // 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.",
+                               fBlockCount-1,
+                               fCurrentBlock->GetDspCount()-1,
+                               fCurrentDSP->GetBusPatchCount()-1
+                       );
+                       break;
+               case kHighErrorDetail:
+               default:
+                       message = Form("%s %s", ErrorCodeToMessage(error), detail);
+                       break;
+               }
+               logAsMajorError = false;
+               break;
+
        case kParityError:
-               fRawStream->GetReader()->AddMinorErrorLog(error, Form("%s [At byte: %d]", msg, pos));
+               fParityErrors++;
+               switch (fRawStream->GetLoggingDetailLevel())
+               {
+               case kLowErrorDetail:
+                       message = "Parity error detected.";
+                       break;
+               case kMediumErrorDetail:
+                       message = Form(
+                               "Parity error in buspatch %d (0x%X).",
+                               fCurrentBusPatch->GetBusPatchId(),
+                               fCurrentBusPatch->GetBusPatchId()
+                       );
+                       break;
+               case kHighErrorDetail:
+               default:
+                       // 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 = (reinterpret_cast<size_t>(location) - reinterpret_cast<size_t>(fCurrentBusPatch->GetData()))
+                               / sizeof(UInt_t);
+                       message = Form(
+                               "Parity error in word %d for manuId %d and channel %d in buspatch %d. %s",
+                               word,
+                               fCurrentBusPatch->GetManuId(word),
+                               fCurrentBusPatch->GetChannelId(word),
+                               fCurrentBusPatch->GetBusPatchId(),
+                               detail
+                       );
+                       break;
+               }
+               logAsMajorError = false;
                break;
+               
+       case kTokenLost:
+               fTokenLostErrors++;
+               switch (fRawStream->GetLoggingDetailLevel())
+               {
+               case kLowErrorDetail:
+                       message = "Lost token error detected.";
+                       break;
+               case kMediumErrorDetail:
+                       word = *reinterpret_cast<const UInt_t*>(location);
+                       message = Form(
+                               "Lost token error detected with address 0x%X of DDL %d and code %d.",
+                               ((word & 0xFFFF0000)),
+                               fRawStream->GetDDL(),
+                               (word & 0xF)
+                       );
+                       break;
+               case kHighErrorDetail:
+               default:
+                       word = *reinterpret_cast<const UInt_t*>(location);
+                       message = Form(
+                               "Lost token error detected with address 0x%X and code %d. %s",
+                               ((word & 0xFFFF0000)),
+                               (word & 0xF),
+                               detail
+                       );
+                       break;
+               }
+               logAsMajorError = false;
+               break;
+
        default:
-               fRawStream->GetReader()->AddMajorErrorLog(error, Form("%s [At byte: %d]", msg, pos));
+               switch (fRawStream->GetLoggingDetailLevel())
+               {
+               case kLowErrorDetail:
+                       message = ErrorCodeToMessage(error);
+                       break;
+               case kMediumErrorDetail:
+                       message = Form(
+                               "%s (At byte %lu)",
+                               ErrorCodeToMessage(error),
+                               (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader)
+                       );
+                       break;
+               case kHighErrorDetail:
+               default:
+                       message = Form(
+                               "%s Error code: %d (%s). %s",
+                               ErrorCodeToMessage(error),
+                               error, ErrorCodeToString(error),
+                               detail
+                       );
+                       break;
+               }
+               logAsMajorError = true;
                break;
        }
+       
+       // Now log the error message depending on the logging flags set.
+       if (fRawStream->IsRawReaderErrorLoggerEnabled())
+       {
+               if (logAsMajorError)
+                       fRawStream->GetReader()->AddMajorErrorLog(Int_t(error), message);
+               else
+                       fRawStream->GetReader()->AddMinorErrorLog(Int_t(error), message);
+       }
+       if (fRawStream->IsMUONErrorLoggerEnabled())
+       {
+               AliMUONLogger* logger = fRawStream->GetMUONErrorLogger();
+               if (logger != NULL)
+               {
+                       logger->Log(message);
+               }
+               else
+               {
+                       AliErrorGeneral(
+                               "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",
+                               "Enabled logging to AliMUONLogger, but the logger object"
+                               " was not set with SetMUONErrorLogger()."
+                       );
+               }
+       }
+       if (fRawStream->IsWarningsEnabled())
+       {
+               AliWarningGeneral(
+                               "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",
+                               message
+                       );
+       }
 }