#include "AliAltroRawStreamV3.h"
#include "AliRawReader.h"
#include "AliLog.h"
+#include "AliAltroRawStream.h"
+#include "AliRawEventHeaderBase.h"
ClassImp(AliAltroRawStreamV3)
fBunchLength(-1),
fBadChannel(kFALSE),
fPayloadSize(-1),
+ fChannelPayloadSize(-1),
+ fBunchDataPointer(NULL),
+ fBunchDataIndex(-1),
fRCUTrailerData(NULL),
fRCUTrailerSize(0),
fFECERRA(0),
fFECERRB(0),
fERRREG2(0),
fERRREG3(0),
- fERRREG4(0),
fActiveFECsA(0),
fActiveFECsB(0),
fAltroCFG1(0),
- fAltroCFG2(0)
+ fAltroCFG2(0),
+ fOldStream(NULL),
+ fCheckAltroPayload(kTRUE)
{
// Constructor
// Create an object to read Altro raw digits in
AliAltroRawStreamV3::~AliAltroRawStreamV3()
{
// destructor
-// nothing to do
+// delete old stream object if one exists
+ if (fOldStream) delete fOldStream;
}
//_____________________________________________________________________________
fBunchLength(stream.fBunchLength),
fBadChannel(stream.fBadChannel),
fPayloadSize(stream.fPayloadSize),
+ fChannelPayloadSize(stream.fChannelPayloadSize),
+ fBunchDataPointer(stream.fBunchDataPointer),
+ fBunchDataIndex(stream.fBunchDataIndex),
fRCUTrailerData(stream.fRCUTrailerData),
fRCUTrailerSize(stream.fRCUTrailerSize),
fFECERRA(stream.fFECERRA),
fFECERRB(stream.fFECERRB),
fERRREG2(stream.fERRREG2),
fERRREG3(stream.fERRREG3),
- fERRREG4(stream.fERRREG4),
fActiveFECsA(stream.fActiveFECsA),
fActiveFECsB(stream.fActiveFECsB),
fAltroCFG1(stream.fAltroCFG1),
- fAltroCFG2(stream.fAltroCFG2)
+ fAltroCFG2(stream.fAltroCFG2),
+ fOldStream(NULL),
+ fCheckAltroPayload(stream.fCheckAltroPayload)
{
// Copy constructor
// Copy the bunch data array
for(Int_t i = 0; i < kMaxNTimeBins; i++) fBunchData[i] = stream.fBunchData[i];
+
+ if (stream.fOldStream)
+ fOldStream = new AliAltroRawStream(*stream.fOldStream);
}
//_____________________________________________________________________________
fBunchLength = stream.fBunchLength;
fBadChannel = stream.fBadChannel;
fPayloadSize = stream.fPayloadSize;
+ fChannelPayloadSize= stream.fChannelPayloadSize;
+ fBunchDataPointer = stream.fBunchDataPointer;
+ fBunchDataIndex = stream.fBunchDataIndex;
fRCUTrailerData = stream.fRCUTrailerData;
fRCUTrailerSize = stream.fRCUTrailerSize;
fFECERRA = stream.fFECERRA;
fFECERRB = stream.fFECERRB;
fERRREG2 = stream.fERRREG2;
fERRREG3 = stream.fERRREG3;
- fERRREG4 = stream.fERRREG4;
fActiveFECsA = stream.fActiveFECsA;
fActiveFECsB = stream.fActiveFECsB;
fAltroCFG1 = stream.fAltroCFG1;
for(Int_t i = 0; i < kMaxNTimeBins; i++) fBunchData[i] = stream.fBunchData[i];
+ if (stream.fOldStream) {
+ if (fOldStream) delete fOldStream;
+ fOldStream = new AliAltroRawStream(stream.fRawReader);
+ *fOldStream = *stream.fOldStream;
+ }
+
+ fCheckAltroPayload = stream.fCheckAltroPayload;
+
return *this;
}
fBunchLength = fStartTimeBin = -1;
fBadChannel = kFALSE;
fPayloadSize = -1;
+ fChannelPayloadSize = -1;
+ fBunchDataPointer = NULL;
+ fBunchDataIndex = -1;
fRCUTrailerData = NULL;
fRCUTrailerSize = 0;
- fFECERRA = fFECERRB = fERRREG2 = fERRREG3 = fERRREG4 = fActiveFECsA = fActiveFECsB = fAltroCFG1 = fAltroCFG2 = 0;
+ fFECERRA = fFECERRB = fERRREG2 = fERRREG3 = fActiveFECsA = fActiveFECsB = fAltroCFG1 = fAltroCFG2 = 0;
if (fRawReader) fRawReader->Reset();
+ if (fOldStream) fOldStream->Reset();
}
//_____________________________________________________________________________
} while (fRawReader->GetDataSize() == 0);
fDDLNumber = fRawReader->GetDDLID();
+ fChannelPayloadSize = -1;
UChar_t rcuVer = fRawReader->GetBlockAttributes();
- if (!ReadRCUTrailer(rcuVer)) return kFALSE;
+ if (rcuVer < 2) {
+ // old altro format data
+ if (!fOldStream) {
+ fOldStream = new AliAltroRawStream(fRawReader);
+ AliInfo(Form("RCU firmware verion %d detected. Using AliAltroRawStream to decode the data.",
+ rcuVer));
+ }
+ Bool_t status = fOldStream->NextDDL(fData);
+ if (status) {
+ fRCUId = fOldStream->GetRCUId();
+ fRCUTrailerSize = fOldStream->GetRCUTrailerSize();
+ fOldStream->GetRCUTrailerData(fRCUTrailerData);
+ fFECERRA = fOldStream->GetFECERRA();
+ fFECERRB = fOldStream->GetFECERRB();
+ fERRREG2 = fOldStream->GetERRREG2();
+ fERRREG3 = ((UInt_t)fOldStream->GetNChAddrMismatch()) |
+ (((UInt_t)fOldStream->GetNChLengthMismatch()) << 12);
+ fActiveFECsA = fOldStream->GetActiveFECsA();
+ fActiveFECsB = fOldStream->GetActiveFECsB();
+ fAltroCFG1 = fOldStream->GetAltroCFG1();
+ fAltroCFG2 = fOldStream->GetAltroCFG2();
+ if (fRawReader->GetType() == AliRawEventHeaderBase::kStartOfData)
+ fPayloadSize = fOldStream->GetRCUPayloadSizeInSOD();
+ }
+ return status;
+ }
- return kTRUE;
+ return ReadRCUTrailer(rcuVer);
}
//_____________________________________________________________________________
// Updates the channel hardware address member and
// channel data size. Sets the error flag in case
// RCU signals readout error in this channel
+ if (fOldStream) {
+ Bool_t status = fOldStream->NextChannel();
+ if (status) {
+ fHWAddress = fOldStream->GetHWAddress();
+ fChannelPayloadSize = fOldStream->GetChannelPayloadSize();
+ }
+ return status;
+ }
+
fCount = -1;
fBadChannel = kFALSE;
+ fBunchDataIndex = 0;
+ fBunchLength = -1;
UInt_t word = 0;
do {
word = Get32bitWord(fPosition++);
- if (fPosition >= fPayloadSize) return kFALSE;
+ if (fPosition > fPayloadSize) return kFALSE;
}
- while (((word >> 30) & 0x3) != 1);
+ while ((word >> 30) != 1);
// check for readout errors
- if ((word >> 29) & 0x1) {
- fBadChannel = kTRUE;
- }
+ fBadChannel = (word >> 29) & 0x1;
// extract channel payload and hw address
- if (!fBadChannel) fCount = (word >> 16) & 0x3FF;
+ fCount = (word >> 16) & 0x3FF;
+ fChannelPayloadSize = fCount;
fHWAddress = word & 0xFFF;
+ // Now unpack the altro data
+ // Revert the order of the samples
+ // inside the bunch so that the
+ // first time is first in the samples
+ // array
+ Int_t isample = 0;
+ Int_t nwords = (fCount+2)/3;
+ for (Int_t iword = 0; iword < nwords; iword++) {
+ word = Get32bitWord(fPosition++);
+ if ((word >> 30) != 0) {
+ // Unexpected end of altro channel payload
+ AliWarning(Form("Unexpected end of payload in altro channel payload! DDL=%03d, Address=0x%x, word=0x%x",
+ fDDLNumber,fHWAddress,word));
+ fRawReader->AddMinorErrorLog(kAltroPayloadErr,Form("hw=0x%x",fHWAddress));
+ if (AliDebugLevel() > 0) HexDumpChannel();
+ fCount = -1;
+ fPosition--;
+ return kFALSE;
+ }
+ fBunchData[isample++] = (word >> 20) & 0x3FF;
+ fBunchData[isample++] = (word >> 10) & 0x3FF;
+ fBunchData[isample++] = word & 0x3FF;
+ }
+
return kTRUE;
}
// raw-data stream.
// Updates the start/end time-bins
// and the array with altro samples
+ if (fOldStream) {
+ Bool_t status = fOldStream->NextBunch(fBunchData,fBunchLength,fStartTimeBin);
+ if (status) fBunchDataPointer = &fBunchData[0];
+ else fBunchDataPointer = NULL;
+ return status;
+ }
+
+ Int_t prevTimeBin = (fBunchLength > 0) ? fStartTimeBin-fBunchLength+1 : 1024;
fBunchLength = fStartTimeBin = -1;
+ fBunchDataPointer = NULL;
- if ((fCount <= 0) || fBadChannel) return kFALSE;
+ if ((fBunchDataIndex >= fCount) || fBadChannel) return kFALSE;
- UInt_t word = Get32bitWord(fPosition++);
- if ((word >> 30) != 0) {
- // Unexpected end of altro channel payload
- AliWarning(Form("Unexpected end of payload in altro channel bunch header! Address=0x%x, word=0x%x",
- fHWAddress,word));
- fRawReader->AddMinorErrorLog(kAltroPayloadErr,Form("hw=0x%x",fHWAddress));
- fPosition--;
- fCount = -1;
+ fBunchLength = fBunchData[fBunchDataIndex];
+ if (fBunchLength <= 2) {
+ // Invalid bunch size
+ AliWarning(Form("Too short bunch length (%d) in Address=0x%x (DDL=%03d)!",
+ fBunchLength,fDDLNumber,fHWAddress));
+ fRawReader->AddMinorErrorLog(kAltroBunchHeadErr,Form("hw=0x%x",fHWAddress));
+ if (AliDebugLevel() > 0) HexDumpChannel();
+ fCount = fBunchLength = -1;
return kFALSE;
}
- fBunchLength = (word >> 20) & 0x3FF;
- if (fBunchLength > fCount) {
+ if ((fBunchDataIndex + fBunchLength) > fCount) {
// Too long bunch detected
- AliWarning(Form("Too long bunch detected in Address=0x%x ! Exptected <= %d 10-bit words, found %d !",
- fCount,fBunchLength));
+ AliWarning(Form("Too long bunch detected in Address=0x%x (DDL=%03d) ! Expected <= %d 10-bit words, found %d !",
+ fHWAddress,fDDLNumber,fCount-fBunchDataIndex,fBunchLength));
fRawReader->AddMinorErrorLog(kAltroBunchHeadErr,Form("hw=0x%x",fHWAddress));
+ if (AliDebugLevel() > 0) HexDumpChannel();
fCount = fBunchLength = -1;
return kFALSE;
}
-
- fCount -= fBunchLength;
-
+ fBunchDataIndex++;
fBunchLength -= 2;
- fStartTimeBin = (word >> 10) & 0x3FF;
-
- Int_t isample = 0;
-
- fBunchData[isample++] = word & 0x3FF; // first sample
-
- Int_t nwords = (fBunchLength+1)/3;
- for (Int_t iword = 0; iword < nwords; iword++) {
- word = Get32bitWord(fPosition++);
- if ((word >> 30) != 0) {
- // Unexpected end of altro channel payload
- AliWarning(Form("Unexpected end of payload in altro channel payload! Address=0x%x, word=0x%x",
- fHWAddress,word));
+ fStartTimeBin = fBunchData[fBunchDataIndex++];
+ if (fCheckAltroPayload) {
+ if ((fStartTimeBin-fBunchLength+1) < 0) {
+ AliWarning(Form("Invalid start time-bin in Address=0x%x (DDL=%03d)! (%d-%d+1) < 0",
+ fHWAddress,fDDLNumber,fStartTimeBin,fBunchLength));
fRawReader->AddMinorErrorLog(kAltroPayloadErr,Form("hw=0x%x",fHWAddress));
- fCount = -1;
- fPosition--;
- return kTRUE;
+ if (AliDebugLevel() > 0) HexDumpChannel();
+ fCount = fBunchLength = -1;
+ return kFALSE;
+ }
+ if (fStartTimeBin >= prevTimeBin) {
+ AliWarning(Form("Invalid start time-bin in Address=0x%x (DDL=%03d)! (%d>=%d)",
+ fHWAddress,fDDLNumber,fStartTimeBin,prevTimeBin));
+ fRawReader->AddMinorErrorLog(kAltroPayloadErr,Form("hw=0x%x",fHWAddress));
+ if (AliDebugLevel() > 0) HexDumpChannel();
+ fCount = fBunchLength = -1;
+ return kFALSE;
}
- fBunchData[isample++] = (word >> 20) & 0x3FF;
- fBunchData[isample++] = (word >> 10) & 0x3FF;
- fBunchData[isample++] = word & 0x3FF;
}
+ fBunchDataPointer = &fBunchData[fBunchDataIndex];
+
+ fBunchDataIndex += fBunchLength;
+
return kTRUE;
}
break;
case 3:
// ERR_REG3
- fERRREG3 = parData & 0xFFF;
+ fERRREG3 = parData & 0x1FFFFFF;
break;
case 4:
- // ERR_REG4
- fERRREG4 = parData & 0xFFF;
- break;
- case 5:
// FEC_RO_A
fActiveFECsA = parData & 0xFFFF;
break;
- case 6:
+ case 5:
// FEC_RO_B
fActiveFECsB = parData & 0xFFFF;
break;
- case 7:
+ case 6:
// RDO_CFG1
fAltroCFG1 = parData & 0xFFFFF;
break;
- case 8:
+ case 7:
// RDO_CFG2
fAltroCFG2 = parData & 0x1FFFFFF;
break;
Double_t tSample = GetTSample();
if (phase >= tSample) {
- AliWarning(Form("Invalid L1 trigger phase (%f >= %d) !",
+ AliWarning(Form("Invalid L1 trigger phase (%f >= %f) !",
phase,tSample));
phase = 0.;
}
if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);
}
+
+//_____________________________________________________________________________
+UChar_t *AliAltroRawStreamV3::GetRCUPayloadInSOD() const
+{
+ // Get a pointer to the data in case
+ // of SOD events
+ if (fRawReader) {
+ if (fRawReader->GetType() == AliRawEventHeaderBase::kStartOfData) {
+ return fData;
+ }
+ }
+ return NULL;
+}
+
+//_____________________________________________________________________________
+Int_t AliAltroRawStreamV3::GetRCUPayloadSizeInSOD() const
+{
+ // Get the size of the RCU data in case
+ // of SOD events
+ if (fRawReader) {
+ if (fRawReader->GetType() == AliRawEventHeaderBase::kStartOfData) {
+ return fPayloadSize;
+ }
+ }
+ return -1;
+}
+
+//_____________________________________________________________________________
+
+void AliAltroRawStreamV3::HexDumpChannel() const
+{
+ // Print of the Hex Data of the current channel
+ // to decipher read-out warnings and errors
+ if (fCount>0 && fPosition>0) {
+ printf("Hex-Dump of DDL: %3d, RCU ID: %d, HWADDR: 0x%03x\n",
+ fDDLNumber,fRCUId,fHWAddress);
+ printf("32-bit - 2bit 10bit 10bit 10bit\n");
+ printf("********** **** ***** ***** *****\n");
+ Int_t nwords = (fCount+2)/3+1;
+ for (Int_t iword = 0; iword < nwords; iword++) {
+ UInt_t word32 = Get32bitWord(fPosition-nwords+iword);
+ UInt_t marker = word32 >> 30 & 0x3;
+ UInt_t word101 = word32 >> 20 & 0x3FF;
+ UInt_t word102 = word32 >> 10 & 0x3FF;
+ UInt_t word103 = word32 >> 00 & 0x3FF; // nice octal number
+ printf("0x%08x - 0b%1d%1d 0x%03x 0x%03x 0x%03x\n",
+ word32,marker>>1,marker&0x1,word101,word102,word103);
+ }
+ }
+}