+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * *
+ * Author: The ALICE Off-line Project. *
+ * Contributors are mentioned in the code where appropriate. *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+
+///////////////////////////////////////////////////////////////////////////////
+///
+/// This class provides access to MUON digits in raw data.
+///
+/// It loops over all MUON digits in the raw data given by the AliRawReader.
+/// The Next method goes to the next digit. If there are no digits left
+/// it returns kFALSE (under develpment)
+/// It can loop also over DDL and store the decoded rawdata in TClonesArray.
+///
+/// First version implement for Tracker
+///
+///////////////////////////////////////////////////////////////////////////////
+
+#include "AliMUONRawStreamTracker.h"
+
+#include "AliRawReader.h"
+#include "AliRawDataHeader.h"
+#include "AliLog.h"
+
+#include "AliMUONDspHeader.h"
+#include "AliMUONBlockHeader.h"
+#include "AliMUONBusStruct.h"
+#include "AliMUONDDLTracker.h"
+
+ClassImp(AliMUONRawStreamTracker)
+
+AliMUONRawStreamTracker::AliMUONRawStreamTracker()
+ : TObject(),
+ fRawReader(0x0),
+ fDDL(0),
+ fBusPatchId(0),
+ fDspId(0),
+ fBlkId(0),
+ fNextDDL(kTRUE),
+ fMaxDDL(20),
+ fMaxBlock(2),
+ fMaxDsp(5),
+ fMaxBus(5)
+{
+ //
+ // create an object to read MUON raw digits
+ // Default ctor for monitoring purposes
+ //
+ fBusPatchManager = new AliMpBusPatch();
+ fBusPatchManager->ReadBusPatchFile();
+
+ fDDLTracker = new AliMUONDDLTracker();
+ fBusStruct = new AliMUONBusStruct();
+ fBlockHeader = new AliMUONBlockHeader();
+ fDspHeader = new AliMUONDspHeader();
+}
+
+//_________________________________________________________________
+AliMUONRawStreamTracker::AliMUONRawStreamTracker(AliRawReader* rawReader)
+ : TObject(),
+ fDDL(0),
+ fBusPatchId(0),
+ fDspId(0),
+ fBlkId(0),
+ fNextDDL(kTRUE),
+ fMaxDDL(20),
+ fMaxBlock(2),
+ fMaxDsp(5),
+ fMaxBus(5)
+{
+ //
+ // ctor with AliRawReader as argument
+ // for reconstruction purpose
+ //
+
+ fRawReader = rawReader;
+
+ fBusPatchManager = new AliMpBusPatch();
+ fBusPatchManager->ReadBusPatchFile();
+
+ fDDLTracker = new AliMUONDDLTracker();
+ fBusStruct = new AliMUONBusStruct();
+ fBlockHeader = new AliMUONBlockHeader();
+ fDspHeader = new AliMUONDspHeader();
+}
+
+//_________________________________________________________________
+AliMUONRawStreamTracker::AliMUONRawStreamTracker(const AliMUONRawStreamTracker& stream) :
+ TObject(stream)
+{
+ //
+ // copy ctor
+ //
+ AliFatal("copy constructor not implemented");
+}
+
+//______________________________________________________________________
+AliMUONRawStreamTracker& AliMUONRawStreamTracker::operator = (const AliMUONRawStreamTracker&
+ /* stream */)
+{
+ //
+ // assignment operator
+ //
+ AliFatal("assignment operator not implemented");
+ return *this;
+}
+
+
+//___________________________________
+AliMUONRawStreamTracker::~AliMUONRawStreamTracker()
+{
+ //
+ // clean up
+ //
+ delete fBusPatchManager;
+ delete fDDLTracker;
+ delete fBusStruct;
+ delete fBlockHeader;
+ delete fDspHeader;
+}
+
+//_____________________________________________________________
+Bool_t AliMUONRawStreamTracker::Next()
+{
+ //
+ // read the next raw digit (buspatch structure)
+ // returns kFALSE if there is no digit left
+ // (under development)
+
+ AliMUONDDLTracker* ddlTracker = 0x0;
+ AliMUONBlockHeader* blkHeader = 0x0;
+ AliMUONDspHeader* dspHeader = 0x0;
+ Int_t nBusPatch;
+ Int_t nDsp;
+ Int_t nBlock;
+
+ next:
+ if (fNextDDL){
+ printf("iDDL %d\n", fDDL+1);
+ fBlkId = 0;
+ fDspId = 0;
+ fBusPatchId = 0;
+ if(!NextDDL())
+ return kFALSE;
+ }
+ fNextDDL = kFALSE;
+
+ ddlTracker = GetDDLTracker();
+
+ nBlock = ddlTracker->GetBlkHeaderEntries();
+ if (fBlkId < nBlock) {
+
+ blkHeader = ddlTracker->GetBlkHeaderEntry(fBlkId);
+ nDsp = blkHeader->GetDspHeaderEntries();
+
+ if( fDspId < nDsp) {
+ dspHeader = blkHeader->GetDspHeaderEntry(fDspId);
+ nBusPatch = dspHeader->GetBusPatchEntries();
+
+ if (fBusPatchId < nBusPatch) {
+ fBusStructPtr = dspHeader->GetBusPatchEntry(fBusPatchId++);
+ return kTRUE;
+
+ } else {// iBusPatch
+ fDspId++;
+ fBusPatchId = 0;
+ goto next;
+ // Next();
+ }
+
+ } else {// iDsp
+ fBlkId++;
+ fDspId = 0;
+ fBusPatchId = 0;
+ goto next;
+ // Next();
+ }
+
+ } else {// iBlock
+ fBlkId = 0;
+ fDspId = 0;
+ fBusPatchId = 0;
+ fNextDDL = kTRUE;
+ //return kTRUE;
+ goto next;
+ }
+
+ return kFALSE;
+}
+
+//______________________________________________________
+Bool_t AliMUONRawStreamTracker::NextDDL()
+{
+ // reading tracker DDL
+ // store buspatch info into Array
+ // store only non-empty structures (buspatch info with datalength !=0)
+
+ fDDLTracker->GetBlkHeaderArray()->Delete();
+ // fDDLTracker->GetBlkHeaderArray()->Clear("C");
+
+ //Read Header Size of DDL,Block,DSP and BusPatch
+
+ Int_t kDDLHeaderSize = sizeof(AliRawDataHeader)/4;;
+ Int_t kBlockHeaderSize = fBlockHeader->GetHeaderLength();
+ Int_t kDspHeaderSize = fDspHeader->GetHeaderLength();
+ Int_t kBusPatchHeaderSize = fBusStruct->GetHeaderLength();
+
+ Int_t totalDDLSize, totalBlockSize, totalDspSize , totalBusPatchSize, dataSize;
+
+
+ Int_t iBusPerDSP[5]; // number of bus patches per DSP
+ Int_t iDspMax; // number max of DSP per block
+
+ // minimum data size (only header's)
+ Int_t blankDDLSize;
+ Int_t blankBlockSize;
+ Int_t blankDspSize;
+
+ if (fDDL >= 20) {
+ fDDL = 0;
+ return kFALSE;
+ }
+ AliDebug(3, Form("DDL Number %d\n", fDDL ));
+
+ // getting DSP info
+ fBusPatchManager->GetDspInfo(fDDL/2, iDspMax, iBusPerDSP);
+
+ // 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.
+ // This information is used to calculate the size of headers (DDL,Block and DSP)
+ // which has no interesting data.
+ blankDDLSize = kDDLHeaderSize + 2*kBlockHeaderSize + 2*iDspMax*kDspHeaderSize;
+ blankBlockSize = kBlockHeaderSize + iDspMax*kDspHeaderSize;
+
+ for (Int_t i = 0; i < iDspMax; i++) {
+ blankDDLSize += 2*iBusPerDSP[i]*kBusPatchHeaderSize;
+ blankBlockSize += iBusPerDSP[i]*kBusPatchHeaderSize;
+ }
+ fRawReader->Reset();
+ fRawReader->Select(0X9, fDDL, fDDL); //Select the DDL file to be read
+
+ fRawReader->ReadHeader();
+
+ // 4 is multiplied to convert 2 bytes words
+ totalDDLSize = (fRawReader->GetDataSize() + sizeof(AliRawDataHeader))/4;
+
+ // Compare the DDL header with an empty DDL header size to read the file
+ if(totalDDLSize > blankDDLSize) {
+
+ Int_t totalDataWord = fRawReader->GetDataSize(); // in bytes
+ UInt_t *buffer = new UInt_t[totalDataWord/4];
+
+ fRawReader->ReadNext((UChar_t*)buffer, totalDataWord);
+
+ // indexes
+ Int_t indexDsp;
+ Int_t indexBusPatch;
+ Int_t index = 0;
+
+ for(Int_t iBlock = 0; iBlock < 2 ;iBlock++){ // loop over 2 blocks
+
+ // copy within padding words
+ memcpy(fBlockHeader->GetHeader(),&buffer[index], (kBlockHeaderSize+1)*4);
+
+ totalBlockSize = fBlockHeader->GetTotalLength();
+
+ fDDLTracker->AddBlkHeader(*fBlockHeader);
+
+ if (fBlockHeader->GetPadding() == 0xDEAD) // skipping padding word
+ index++;
+
+ if(totalBlockSize > blankBlockSize) { // compare block header
+ index += kBlockHeaderSize;
+
+ for(Int_t iDsp = 0; iDsp < iDspMax ;iDsp++){ //DSP loop
+
+ if (iDsp > fMaxDsp) break;
+
+ memcpy(fDspHeader->GetHeader(),&buffer[index], kDspHeaderSize*4);
+
+ totalDspSize = fDspHeader->GetTotalLength();
+ indexDsp = index;
+
+ blankDspSize = kDspHeaderSize + iBusPerDSP[iDsp]*kBusPatchHeaderSize; // no data just header
+
+ fDDLTracker->AddDspHeader(*fDspHeader, iBlock);
+
+ if(totalDspSize > blankDspSize) { // Compare DSP Header
+ index += kDspHeaderSize;
+
+ for(Int_t iBusPatch = 0; iBusPatch < iBusPerDSP[iDsp]; iBusPatch++) {
+
+ if (iBusPatch > fMaxBus) break;
+
+ //copy buffer into header structure
+ memcpy(fBusStruct->GetBusPatchHeader(), &buffer[index], kBusPatchHeaderSize*4);
+
+ totalBusPatchSize = fBusStruct->GetTotalLength();
+ indexBusPatch = index;
+
+ //Check Buspatch header, not empty events
+ if(totalBusPatchSize > kBusPatchHeaderSize) {
+
+ index += kBusPatchHeaderSize;
+ dataSize = fBusStruct->GetLength();
+ Int_t bufSize = fBusStruct->GetBufSize();
+
+ if(dataSize > 0) { // check data present
+ if (dataSize > bufSize) 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);
+ fDDLTracker->AddBusPatch(*fBusStruct, iBlock, iDsp);
+
+ } // dataSize test
+
+ } // testing buspatch
+
+ index = indexBusPatch + totalBusPatchSize;
+
+ } //buspatch loop
+
+ } // dsp test
+
+ index = indexDsp + totalDspSize;
+
+ } // dsp loop
+
+ } //block test
+
+ index = totalBlockSize;
+
+ } //block loop
+
+ delete[] buffer;
+ } //loop checking the header size of DDL
+
+
+ fDDL++;
+
+ return kTRUE;
+}
+//______________________________________________________
+void AliMUONRawStreamTracker::ResetDDL()
+{
+ // reseting TClonesArray
+ // after each DDL
+ //
+ fDDLTracker->GetBlkHeaderArray()->Clear("C");
+}
+
+//______________________________________________________
+void AliMUONRawStreamTracker::SetMaxDDL(Int_t ddl)
+{
+ // set DDL number
+ if (ddl > 20) ddl = 20;
+ fMaxDDL = ddl;
+}
+
+//______________________________________________________
+void AliMUONRawStreamTracker::SetMaxBlock(Int_t blk)
+{
+ // set regional card number
+ if (blk > 2) blk = 2;
+ fMaxBlock = blk;
+}