//-----------------------------------------------------------------------------
#include "AliMUONRawStreamTrackerHP.h"
+#include "AliMUONTrackerDDLDecoder.h"
+#include "AliMUONDspHeader.h"
+#include "AliMUONBlockHeader.h"
+#include "AliMUONBusStruct.h"
+#include "AliMUONDDLTracker.h"
#include "AliRawReader.h"
#include "AliLog.h"
#include <cassert>
#include <iostream>
-#include <iomanip>
using std::cout;
using std::endl;
using std::hex;
fDDL(0),
fBufferSize(8192),
fBuffer(new UChar_t[8192]),
- fCurrentBusPatch(NULL),
- fCurrentData(NULL),
- fEndOfData(NULL),
+ fkCurrentBusPatch(NULL),
+ fkCurrentData(NULL),
+ fkEndOfData(NULL),
fHadError(kFALSE),
- fDone(kFALSE)
+ fDone(kFALSE),
+ fDDLObject(NULL)
{
///
/// Default constructor.
fDDL(0),
fBufferSize(8192),
fBuffer(new UChar_t[8192]),
- fCurrentBusPatch(NULL),
- fCurrentData(NULL),
- fEndOfData(NULL),
+ fkCurrentBusPatch(NULL),
+ fkCurrentData(NULL),
+ fkEndOfData(NULL),
fHadError(kFALSE),
- fDone(kFALSE)
+ fDone(kFALSE),
+ fDDLObject(NULL)
{
///
/// Constructor with AliRawReader as argument.
{
delete [] fBuffer;
}
+ if (fDDLObject != NULL)
+ {
+ delete fDDLObject;
+ }
}
assert( GetReader() != NULL );
+ // The temporary object if generated in GetDDLTracker, is now stale,
+ // so delete it.
+ if (fDDLObject != NULL)
+ {
+ delete fDDLObject;
+ fDDLObject = NULL;
+ }
+
+ // Better to reset these pointers.
+ fkCurrentBusPatch = NULL;
+ fkCurrentData = NULL;
+ fkEndOfData = NULL;
+
while (fDDL < GetMaxDDL())
{
GetReader()->Reset();
}
// If we reach the end of the DDL list for this event then reset the
- // DDL counter, mark the iteration as done and
+ // DDL counter, mark the iteration as done and exit.
if (fDDL >= GetMaxDDL())
{
fDDL = 0;
}
#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
bool result = false;
}
// Update the current bus patch pointers.
- fCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch();
- if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
+ fkCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch();
+ if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
{
- fCurrentData = fCurrentBusPatch->GetData();
- fEndOfData = fCurrentData + fCurrentBusPatch->GetDataCount();
+ 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.
- fCurrentData = fEndOfData = NULL;
+ fkCurrentData = fkEndOfData = NULL;
}
fDDL++; // Remember to increment index to next DDL.
- return result;
+ return kTRUE;
}
Bool_t AliMUONRawStreamTrackerHP::Next(
Int_t& busPatchId, UShort_t& manuId, UChar_t& manuChannel,
- UShort_t& adc
+ UShort_t& adc, Bool_t skipParityErrors
)
{
/// Advance one step in the iteration. Returns false if finished.
/// [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 (fkCurrentData == NULL) return kFALSE;
+
+ fDecoder.SendDataOnParityError(skipParityErrors);
+
retry:
// Check if we still have data to be returned for the current bus patch.
- if (fCurrentData != fEndOfData)
+ if (fkCurrentData != fkEndOfData)
{
- busPatchId = fCurrentBusPatch->GetBusPatchId();
- AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fCurrentData, manuId, manuChannel, adc);
- fCurrentData++;
+ busPatchId = fkCurrentBusPatch->GetBusPatchId();
+ AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fkCurrentData, manuId, manuChannel, adc);
+ fkCurrentData++;
return kTRUE;
}
else
// 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 (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
{
- fCurrentBusPatch++;
- if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
+ fkCurrentBusPatch++;
+ if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
{
- fCurrentData = fCurrentBusPatch->GetData();
- fEndOfData = fCurrentData + fCurrentBusPatch->GetDataCount();
+ fkCurrentData = fkCurrentBusPatch->GetData();
+ fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount();
goto retry;
}
}
}
+AliMUONDDLTracker* AliMUONRawStreamTrackerHP::GetDDLTracker() const
+{
+ /// 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++)
+ {
+ 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++)
+ {
+ 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();
+ }
+ }
+ }
+
+ return fDDLObject;
+}
+
+
void AliMUONRawStreamTrackerHP::SetMaxBlock(Int_t blk)
{
/// Set maximum number of blocks per DDL allowed.
fBlocks = new AliBlockHeader[maxBlocks];
fDSPs = new AliDspHeader[maxBlocks*maxDsps];
fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches];
- fEndOfBusPatches = fEndOfBusPatches;
+ fEndOfBusPatches = fBusPatches;
}
/// 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 raw reader.
/// \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.
switch (error)
{
case kGlitchFound:
+ fGlitchErrors++;
message = Form(
"Glitch error detected in DSP %d, skipping event ",
fCurrentBlock->GetDspId()
break;
case kBadPaddingWord:
+ fPaddingErrors++;
// We subtract 1 from the current numbers of blocks, DSPs
// and bus patches to get the indices.
message = Form(
break;
case kParityError:
+ fParityErrors++;
// 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
message = Form(
"%s (At byte %d in DDL.)",
ErrorCodeToMessage(error),
- (unsigned long)location - (unsigned long)fBufferStart
+ (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader)
);
fRawStream->GetReader()->AddMajorErrorLog(error, message);
break;