* provided "as is" without express or implied warranty. *
**************************************************************************/
+// $Id$
-///////////////////////////////////////////////////////////////////////////////
-///
-/// Class Payload
-///
+//-----------------------------------------------------------------------------
+/// \class AliMUONPayloadTracker
/// Decodes rawdata from buffer and stores in TClonesArray.
-///
/// First version implement for Tracker
///
-///////////////////////////////////////////////////////////////////////////////
+/// \author Christian Finck
+//-----------------------------------------------------------------------------
-#include "AliMUONPayloadTracker.h"
+#include <TObjString.h>
-#include "AliRawReader.h"
-#include "AliRawDataHeader.h"
-#include "AliLog.h"
+#include "AliMUONPayloadTracker.h"
#include "AliMUONDspHeader.h"
#include "AliMUONBlockHeader.h"
#include "AliMUONBusStruct.h"
#include "AliMUONDDLTracker.h"
+#include "AliMUONLogger.h"
+#include "AliLog.h"
+
+/// \cond CLASSIMP
ClassImp(AliMUONPayloadTracker)
+/// \endcond
AliMUONPayloadTracker::AliMUONPayloadTracker()
: TObject(),
+ fBusPatchId(0),
+ fDspId(0),
+ fBlkId(0),
+ fMaxDDL(20),
fMaxBlock(2),
fMaxDsp(5),
- fMaxBus(5)
+ fMaxBus(5),
+ fDDLTracker(new AliMUONDDLTracker()),
+ fBusStruct(new AliMUONBusStruct()),
+ fBlockHeader(new AliMUONBlockHeader()),
+ fDspHeader(new AliMUONDspHeader()),
+ fLog(new AliMUONLogger(1000)),
+ fParityErrors(0),
+ fGlitchErrors(0),
+ fPaddingErrors(0),
+ fWarnings(kTRUE)
{
- //
- // create an object to decode MUON payload
- //
-
- fDDLTracker = new AliMUONDDLTracker();
- fBusStruct = new AliMUONBusStruct();
- fBlockHeader = new AliMUONBlockHeader();
- fDspHeader = new AliMUONDspHeader();
-}
-
-//_________________________________________________________________
-AliMUONPayloadTracker::AliMUONPayloadTracker(const AliMUONPayloadTracker& stream) :
- TObject(stream)
-{
- //
- // copy ctor
- //
- AliFatal("copy constructor not implemented");
-}
+ ///
+ /// create an object to decode MUON payload
+ ///
-//______________________________________________________________________
-AliMUONPayloadTracker& AliMUONPayloadTracker::operator = (const AliMUONPayloadTracker&
- /* stream */)
-{
- //
- // assignment operator
- //
- AliFatal("assignment operator not implemented");
- return *this;
}
-
//___________________________________
AliMUONPayloadTracker::~AliMUONPayloadTracker()
{
- //
- // clean up
- //
+ ///
+ /// clean up
+ ///
delete fDDLTracker;
delete fBusStruct;
delete fBlockHeader;
delete fDspHeader;
+ delete fLog;
}
//______________________________________________________
Bool_t AliMUONPayloadTracker::Decode(UInt_t* buffer, Int_t totalDDLSize)
{
- // Each DDL is made with 2 Blocks each of which consists of 5 DSP's at most
- // and each of DSP has at most 5 buspatches.
- // The different structures, Block (CRT), DSP (FRT) and Buspatch,
- // are identified by a key word 0xFC0000FC, 0xF000000F and 0xB000000B respectively.
- // (fBusPatchManager no more needed !)
+ /// Each DDL is made with 2 Blocks each of which consists of 5 DSP's at most
+ /// and each of DSP has at most 5 buspatches.
+ /// The different structures, Block (CRT), DSP (FRT) and Buspatch,
+ /// are identified by a key word 0xFC0000FC, 0xF000000F and 0xB000000B respectively.
+ /// (fBusPatchManager no more needed !)
//Read Header Size of DDL,Block,DSP and BusPatch
// CROCUS CRT
while (buffer[index] == fBlockHeader->GetDefaultDataKey()) {
-
+
if (iBlock > fMaxBlock) break;
-
+
// copy within padding words
memcpy(fBlockHeader->GetHeader(),&buffer[index], (kBlockHeaderSize)*4);
-
+
totalBlockSize = fBlockHeader->GetTotalLength();
-
+
indexBlk = index;
index += kBlockHeaderSize;
-
+
// copy in TClonesArray
fDDLTracker->AddBlkHeader(*fBlockHeader);
-
+
// Crocus FRT
Int_t iDsp = 0;
while (buffer[index] == fDspHeader->GetDefaultDataKey()) {
-
+
if (iDsp > fMaxDsp) break; // if ever...
-
+
memcpy(fDspHeader->GetHeader(),&buffer[index], kDspHeaderSize*4);
-
+
totalDspSize = fDspHeader->GetTotalLength();
+
+ if (fDspHeader->GetErrorWord()) {
+ // fDspHeader->Print("");
+ if ( fDspHeader->GetErrorWord() == (0x000000B1 | fBlockHeader->GetDspId())
+ || fDspHeader->GetErrorWord() == (0x00000091 | fBlockHeader->GetDspId()) ){
+ // an event with a glitch in the readout has been detected
+ // it means that somewhere a 1 byte word has been randomly inserted
+ // all the readout sequence is shifted untill the next event
+
+ Char_t* msg = Form("Glitch error detected in DSP %d, skipping event ", fBlockHeader->GetDspId());
+
+ if (fWarnings) AliWarning(msg);
+ AddErrorMessage(msg);
+ fGlitchErrors++;
+ return kFALSE ;
+ }
+ }
+
indexDsp = index;
index += kDspHeaderSize;
-
-// if (fDspHeader->GetPaddingWord() != fDspHeader->GetDefaultPaddingWord()) {
-// // copy the field of Padding word into ErrorWord field
-// fDspHeader->SetErrorWord(fDspHeader->GetPaddingWord());
-// index--;
-// }
-
+
// copy in TClonesArray
fDDLTracker->AddDspHeader(*fDspHeader, iBlock);
-
+
// buspatch structure
Int_t iBusPatch = 0;
while (buffer[index] == fBusStruct->GetDefaultDataKey()) {
-
- if (iBusPatch > fMaxBus) break; // if ever
-
- //copy buffer into header structure
- memcpy(fBusStruct->GetHeader(), &buffer[index], kBusPatchHeaderSize*4);
-
- totalBusPatchSize = fBusStruct->GetTotalLength();
- indexBusPatch = index;
-
- //Check Buspatch header, not empty events
- if(totalBusPatchSize > kBusPatchHeaderSize) {
-
- index += kBusPatchHeaderSize;
- dataSize = fBusStruct->GetLength();
- bufSize = fBusStruct->GetBufSize();
-
- if(dataSize > 0) { // check data present
- if (dataSize > bufSize) // check buffer size
- fBusStruct->SetAlloc(dataSize);
-
- //copy buffer into data structure
- memcpy(fBusStruct->GetData(), &buffer[index], dataSize*4);
- fBusStruct->SetBlockId(iBlock); // could be usefull in future applications ?
- fBusStruct->SetDspId(iDsp);
-
- // copy in TClonesArray
- fDDLTracker->AddBusPatch(*fBusStruct, iBlock, iDsp);
-
- } // dataSize test
-
- } // testing buspatch
-
- index = indexBusPatch + totalBusPatchSize;
- if (index >= totalDDLSize) {// check the end of DDL
- index = totalDDLSize - 1; // point to the last element of buffer
- break;
- }
- iBusPatch++;
+
+ if (iBusPatch > fMaxBus) break; // if ever
+
+ //copy buffer into header structure
+ memcpy(fBusStruct->GetHeader(), &buffer[index], kBusPatchHeaderSize*4);
+
+ totalBusPatchSize = fBusStruct->GetTotalLength();
+ indexBusPatch = index;
+
+ //Check Buspatch header, not empty events
+ if(totalBusPatchSize > kBusPatchHeaderSize) {
+
+ index += kBusPatchHeaderSize;
+ dataSize = fBusStruct->GetLength();
+ bufSize = fBusStruct->GetBufSize();
+
+ if(dataSize > 0) { // check data present
+ if (dataSize > bufSize) // check buffer size
+ fBusStruct->SetAlloc(dataSize);
+
+ //copy buffer into data structure
+ memcpy(fBusStruct->GetData(), &buffer[index], dataSize*4);
+ fBusStruct->SetBlockId(iBlock); // could be usefull in future applications ?
+ fBusStruct->SetDspId(iDsp);
+
+ // check parity
+ if(!CheckDataParity()) {
+ fParityErrors++;
+ return kFALSE;
+ }
+
+ // copy in TClonesArray
+ fDDLTracker->AddBusPatch(*fBusStruct, iBlock, iDsp);
+
+ } // dataSize test
+
+ } // testing buspatch
+
+ index = indexBusPatch + totalBusPatchSize;
+ if (index >= totalDDLSize) {// check the end of DDL
+ index = totalDDLSize - 1; // point to the last element of buffer
+ break;
+ }
+ iBusPatch++;
} // buspatch loop
-
+
// skipping additionnal word if padding
if (fDspHeader->GetPaddingWord() == 1) {
- if (buffer[index++] != fDspHeader->GetDefaultPaddingWord())
- AliWarning(Form("Error in padding word for iBlock %d, iDsp %d, iBus %d\n",
- iBlock, iDsp, iBusPatch));
+ if (buffer[index++] != fDspHeader->GetDefaultPaddingWord()) {
+
+ Char_t *msg = Form("Padding word error for iBlock %d, iDsp %d, iBus %d\n",
+ iBlock, iDsp, iBusPatch);
+
+ if (fWarnings) AliWarning(msg);
+ AddErrorMessage(msg);
+ fPaddingErrors++;
+ }
}
-
+
index = indexDsp + totalDspSize;
if (index >= totalDDLSize) {
- index = totalDDLSize - 1;
- break;
+ index = totalDDLSize - 1;
+ break;
}
iDsp++;
} // dsp loop
-
+
index = indexBlk + totalBlockSize;
if (index >= totalDDLSize) {
index = totalDDLSize - 1;
break;
}
+
iBlock++;
} // block loop
-
+
+ if (buffer[index++] != fBlockHeader->GetDdlDataKey() ||
+ buffer[index++] != fBlockHeader->GetDdlDataKey()) {
+
+ Char_t *msg = Form("Bad end of DDL data key\n");
+
+ if (fWarnings) AliWarning(msg);
+ AddErrorMessage(msg);
+ }
+
+
return kTRUE;
}
//______________________________________________________
void AliMUONPayloadTracker::ResetDDL()
{
- // reseting TClonesArray
- // after each DDL
- //
+ /// reseting TClonesArray
+ /// after each DDL
+ ///
fDDLTracker->GetBlkHeaderArray()->Delete();
+ fGlitchErrors = 0;
+ fPaddingErrors = 0;
+ fParityErrors = 0;
+
}
//______________________________________________________
void AliMUONPayloadTracker::SetMaxBlock(Int_t blk)
{
- // set regional card number
+ /// set regional card number
if (blk > 2) blk = 2;
fMaxBlock = blk;
}
+
+//______________________________________________________
+Bool_t AliMUONPayloadTracker::CheckDataParity()
+{
+ /// parity check
+ /// taken from MuTrkBusPatch.cxx (sotfware test for CROCUS)
+ /// A. Baldisseri
+
+ Int_t parity;
+ UInt_t data;
+
+ Int_t dataSize = fBusStruct->GetLength();
+ for (int idata = 0; idata < dataSize; idata++) {
+
+ data = fBusStruct->GetData(idata);
+
+ // Compute the parity for each data word
+ parity = data & 0x1;
+ for (Int_t i = 1; i <= 30; i++)
+ parity ^= ((data >> i) & 0x1);
+
+ // Check
+ if (parity != fBusStruct->GetParity(idata)) {
+
+ Char_t* msg = Form("Parity error in word %d for manuId %d and channel %d in buspatch %d\n",
+ idata, fBusStruct->GetManuId(idata), fBusStruct->GetChannelId(idata),
+ fBusStruct->GetBusPatchId());
+
+ if (fWarnings) AliWarning(msg);
+ AddErrorMessage(msg);
+ fParityErrors++;
+
+ return kFALSE;
+
+ }
+ }
+ return kTRUE;
+}
+
+//______________________________________________________
+void AliMUONPayloadTracker::AddErrorMessage(const Char_t* msg)
+{
+/// adding message to logger
+
+ TString tmp(msg);
+
+ Int_t pos = tmp.First("\n");
+ tmp[pos] = 0;
+
+ fLog->Log(tmp.Data());
+}
+
+