#include "AliAltroRawStream.h"
#include "AliRawReader.h"
#include "AliLog.h"
+#include "AliRawEventHeaderBase.h"
ClassImp(AliAltroRawStream)
//_____________________________________________________________________________
AliAltroRawStream::AliAltroRawStream(AliRawReader* rawReader) :
- fNoAltroMapping(kTRUE),
- fIsOldRCUFormat(kFALSE),
fIsShortDataHeader(kFALSE),
fDDLNumber(-1),
fPrevDDLNumber(-1),
fData(NULL),
fPosition(0),
fCount(0),
+ fChannelPayloadSize(-1),
fBunchLength(0),
fRCUTrailerData(NULL),
- fRCUTrailerSize(0)
+ fRCUTrailerSize(0),
+ fFECERRA(0),
+ fFECERRB(0),
+ fERRREG2(0),
+ fERRREG3(0),
+ fERRREG4(0),
+ fActiveFECsA(0),
+ fActiveFECsB(0),
+ fAltroCFG1(0),
+ fAltroCFG2(0)
{
// create an object to read Altro raw digits
- fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
}
//_____________________________________________________________________________
AliAltroRawStream::AliAltroRawStream(const AliAltroRawStream& stream) :
TObject(stream),
- fNoAltroMapping(kTRUE),
- fIsOldRCUFormat(kFALSE),
- fIsShortDataHeader(kFALSE),
- fDDLNumber(-1),
- fPrevDDLNumber(-1),
- fRCUId(-1),
- fPrevRCUId(-1),
- fHWAddress(-1),
- fPrevHWAddress(-1),
- fTime(-1),
- fPrevTime(-1),
- fSignal(-1),
- fTimeBunch(-1),
- fRawReader(NULL),
- fData(NULL),
- fPosition(0),
- fCount(0),
- fBunchLength(0),
- fRCUTrailerData(NULL),
- fRCUTrailerSize(0)
+ fIsShortDataHeader(stream.fIsShortDataHeader),
+ fDDLNumber(stream.fDDLNumber),
+ fPrevDDLNumber(stream.fPrevDDLNumber),
+ fRCUId(stream.fRCUId),
+ fPrevRCUId(stream.fPrevRCUId),
+ fHWAddress(stream.fHWAddress),
+ fPrevHWAddress(stream.fPrevHWAddress),
+ fTime(stream.fTime),
+ fPrevTime(stream.fPrevTime),
+ fSignal(stream.fSignal),
+ fTimeBunch(stream.fTimeBunch),
+ fRawReader(stream.fRawReader),
+ fData(stream.fData),
+ fPosition(stream.fPosition),
+ fCount(stream.fCount),
+ fChannelPayloadSize(stream.fChannelPayloadSize),
+ fBunchLength(stream.fBunchLength),
+ 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)
{
- Fatal("AliAltroRawStream", "copy constructor not implemented");
}
//_____________________________________________________________________________
-AliAltroRawStream& AliAltroRawStream::operator = (const AliAltroRawStream&
- /* stream */)
+AliAltroRawStream& AliAltroRawStream::operator = (const AliAltroRawStream& stream)
{
- Fatal("operator =", "assignment operator not implemented");
+ if(&stream == this) return *this;
+
+ fIsShortDataHeader = stream.fIsShortDataHeader;
+ fDDLNumber = stream.fDDLNumber;
+ fPrevDDLNumber = stream.fPrevDDLNumber;
+ fRCUId = stream.fRCUId;
+ fPrevRCUId = stream.fPrevRCUId;
+ fHWAddress = stream.fHWAddress;
+ fPrevHWAddress = stream.fPrevHWAddress;
+ fTime = stream.fTime;
+ fPrevTime = stream.fPrevTime;
+ fSignal = stream.fSignal;
+ fTimeBunch = stream.fTimeBunch;
+ fRawReader = stream.fRawReader;
+ fData = stream.fData;
+ fPosition = stream.fPosition;
+ fCount = stream.fCount;
+ fChannelPayloadSize= stream.fChannelPayloadSize;
+ fBunchLength = stream.fBunchLength;
+ 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;
+
return *this;
}
// reset altro raw stream params
fPosition = fCount = fBunchLength = 0;
+ fChannelPayloadSize = -1;
fRCUTrailerData = NULL;
fRCUTrailerSize = 0;
+ fFECERRA = fFECERRB = fERRREG2 = fERRREG3 = fERRREG4 = fActiveFECsA = fActiveFECsB = fAltroCFG1 = fAltroCFG2 = 0;
+
fDDLNumber = fPrevDDLNumber = fRCUId = fPrevRCUId = fHWAddress = fPrevHWAddress = fTime = fPrevTime = fSignal = fTimeBunch = -1;
if (fRawReader) fRawReader->Reset();
-
- fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
}
//_____________________________________________________________________________
fPrevTime = fTime;
while (fCount == 0) { // next trailer
- if (fPosition <= 0) { // next payload
+ while (fPosition <= 0) { // next payload
do {
if (!fRawReader->ReadNextData(fData)) return kFALSE;
} while (fRawReader->GetDataSize() == 0);
return kTRUE;
}
+//_____________________________________________________________________________
+Bool_t AliAltroRawStream::NextDDL(UChar_t *data)
+{
+ if (!data) {
+ do {
+ if (!fRawReader->ReadNextData(fData)) return kFALSE;
+ } while (fRawReader->GetDataSize() == 0);
+ }
+ else {
+ fData = data;
+ }
+
+ fDDLNumber = fRawReader->GetDDLID();
+ fChannelPayloadSize = -1;
+ fPosition = GetPosition();
+
+ return kTRUE;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAltroRawStream::NextChannel()
+{
+ if (fPosition <= 0) return kFALSE;
+
+ ReadTrailer();
+
+ return kTRUE;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAltroRawStream::NextBunch(UShort_t *bunchData,
+ Int_t &bunchLength,
+ Int_t &startTimeBin)
+{
+ if (fCount == 0) return kFALSE;
+
+ ReadBunch();
+ bunchLength = fTimeBunch;
+ startTimeBin = fTime;
+
+ while (fBunchLength > 0) {
+ ReadAmplitude();
+ bunchData[bunchLength-fBunchLength-1] = fSignal;
+ }
+
+ return kTRUE;
+}
+
//_____________________________________________________________________________
void AliAltroRawStream::SelectRawData(Int_t detId)
{
Bool_t AliAltroRawStream::ReadTrailer()
{
//Read a trailer of 40 bits in the backward reading mode
- //In case of no mapping is provided, read a dummy trailer
- if (fNoAltroMapping) {
- AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
- return ReadDummyTrailer();
- }
-
//First reading filling words
UShort_t temp;
Int_t nFillWords = 0;
if (nFillWords == 0) {
fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0x2AA");
// PrintDebug();
- AliWarning("Incorrect trailer found ! Expected 0x2AA not found !");
+ AliWarning(Form("Incorrect trailer found ! Expected 0x2AA not found (0x%x != 0x2AA) ! Current position %d, DDL=%d",
+ temp,fPosition,fDDLNumber));
// trying to recover and find the next bunch
- while ((fPosition > 5) && (temp != 0x2AA)) temp = GetNextWord();
+ while ((fPosition > 2) && (temp != 0x2AA)) temp = GetNextWord();
if (temp != 0x2AA) {
fCount = fPosition = 0;
return kFALSE;
}
//Then read the trailer
- if (fPosition < 5) {
+ if (fPosition < 2) {
fRawReader->AddMajorErrorLog(kAltroTrailerErr,Form("size %d < 5",
- fPosition));
+ fPosition));
// PrintDebug();
AliWarning(Form("Incorrect raw data size ! Expected at least 5 words but found %d !",fPosition));
fCount = fPosition = 0;
return kFALSE;
}
fCount |= ((temp & 0x3FF) >> 6);
- if (fCount == 0) return kFALSE;
+ fChannelPayloadSize = fCount;
+ if (fCount >= fPosition) {
+ fRawReader->AddMajorErrorLog(kAltroTrailerErr,"invalid size");
+ // PrintDebug();
+ AliWarning(Form("Incorrect trailer found ! The altro payload size is invalid (%d >= %d) !",fCount,fPosition));
+ fCount = 0;
+ return kFALSE;
+ }
temp = GetNextWord();
fHWAddress |= temp;
return kTRUE;
}
-//_____________________________________________________________________________
-Bool_t AliAltroRawStream::ReadDummyTrailer()
-{
- //Read a trailer of 40 bits in the backward reading mode
- //In case of no mapping is provided, read a dummy trailer
- UShort_t temp;
- while ((temp = GetNextWord()) == 0x2AA);
-
- fSegmentation[0] = temp;
- fSegmentation[1] = GetNextWord();
- fSegmentation[2] = GetNextWord();
- fCount = GetNextWord();
- if (fCount == 0) return kFALSE;
- fHWAddress = -1;
-
- fPosition -= (4 - (fCount % 4)) % 4; // skip fill words
-
- return kTRUE;
-}
-
//_____________________________________________________________________________
void AliAltroRawStream::ReadBunch()
{
// Read altro payload in
// backward direction
- if (fPosition <= 0) {
+ if (fCount <= 2) {
fRawReader->AddMinorErrorLog(kBunchLengthReadErr,"");
// PrintDebug();
- AliWarning("Could not read bunch length !");
+ AliWarning(Form("Could not read bunch length and time bin ! Only %d 10-bit words are left !",fCount));
+ fBunchLength = fTimeBunch = fCount = 0;
+ return;
}
fBunchLength = GetNextWord() - 2;
- fTimeBunch = fBunchLength;
- fCount--;
-
- if (fPosition <= 0) {
- fRawReader->AddMinorErrorLog(kTimeBinReadErr,"");
+ if (fBunchLength > fCount) {
+ fRawReader->AddMinorErrorLog(kBunchLengthReadErr,Form("bl=%d",fBunchLength));
// PrintDebug();
- AliWarning("Could not read time bin !");
+ AliWarning(Form("Could not read bunch length ! Bunch length = %d (>%d)",fBunchLength,fCount));
+ fBunchLength = fTimeBunch = fCount = 0;
+ return;
}
+ fTimeBunch = fBunchLength;
+ fCount--;
fTime = GetNextWord();
fCount--;
void AliAltroRawStream::ReadAmplitude()
{
// Read next time bin amplitude
- if (fPosition <= 0) {
+ if (fCount <= 0) {
fRawReader->AddMinorErrorLog(kAmplitudeReadErr,"");
// PrintDebug();
AliWarning("Could not read sample amplitude !");
+ fCount = fSignal = fBunchLength = 0;
+ return;
}
fSignal = GetNextWord();
+
fCount--;
fBunchLength--;
// The RCU trailer format is described
// in details in the RCU manual.
- if (!fIsOldRCUFormat) {
- // First read 32-bit word with the
- // trailer size (22 bits) and RCU ID (the rest)
- Int_t index = fRawReader->GetDataSize();
- UInt_t word = Get32bitWord(index);
- fRCUId = (Int_t)(word >> 22);
- Int_t trailerSize = (word & 0x3FFFFF);
+ // We use the last word of the payload
+ // in order to decide which RCU firmware
+ // was used during the data taking.
+ // The firmware v2 adds 0xAAAA as 16
+ // most significant bits and since the
+ // payload size (firmware v1) can not be
+ // that big, we use this as a unique
+ // label of the firmware version.
+
+ Int_t index = fRawReader->GetDataSize();
+ UInt_t word = Get32bitWord(index);
+ if (((word >> 16) == 0xaaaa) || (word == 2)) {
+ // This is RCU formware v2
+ // The statement word==2 is needed only temporary
+ // in order to be able to read previously generated
+ // aliroot raw data
+
+ Int_t trailerSize = 0;
+ if (word == 2) {
+ AliInfo("Old simulated raw data is assumed!");
+ trailerSize = 2;
+ fRCUId = 0;
+ }
+ else {
+ // First read 32-bit word with the
+ // trailer size (7 bits), RCU ID (9 bits) and
+ // 0xAAA (the rest - 16 bits)
+ fRCUId = (Int_t)((word >> 7) & 0x1ff);
+ trailerSize = (word & 0x7F);
+ }
// Now read the beginning of the trailer
// where the payload size is written
if (trailerSize < 2) {
- PrintDebug();
- AliFatal(Form("Invalid trailer size found (%d bytes) !",trailerSize*4));
- }
- fRCUTrailerSize = (trailerSize-2)*4;
- index -= fRCUTrailerSize;
- if (index < 4) {
- PrintDebug();
- AliFatal(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
- trailerSize*4,
- fRawReader->GetDataSize()));
+ fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes",
+ trailerSize*4));
+ AliWarning(Form("Invalid trailer size found (%d bytes) !",
+ trailerSize*4));
}
- fRCUTrailerData = fData + index;
- Int_t position = Get32bitWord(index);
- // The size is specified in a number of 40bits
- // Therefore we need to transform it to number of bytes
- position *= 5;
- // Check the consistency of the header and trailer
- if ((fRawReader->GetDataSize() - trailerSize*4) != position) {
- PrintDebug();
- AliFatal(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
- fRawReader->GetDataSize(),
- trailerSize*4,
- position));
- }
+ Int_t position = ReadRCUTrailer(index,trailerSize);
+ if (fRawReader->GetType() != AliRawEventHeaderBase::kStartOfData) {
+ // The size is specified in a number of 40bits
+ // Therefore we need to transform it to number of bytes
+ position *= 5;
+
+ // Check the consistency of the header and trailer
+ if (((fRawReader->GetDataSize() - trailerSize*4) < position) ||
+ ((fRawReader->GetDataSize() - trailerSize*4) >= (position + 4))) {
+ fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d tr=%d rcu=%d bytes",
+ fRawReader->GetDataSize(),
+ trailerSize*4,
+ position));
+ AliWarning(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
+ fRawReader->GetDataSize(),
+ trailerSize*4,
+ position));
+ position = fRawReader->GetDataSize() - trailerSize*4;
+ }
- return position * 8 / 10;
+ return position * 8 / 10;
+ }
+ else {
+ // Special RCU payload in case of SOD events
+ // The decoding is left to the user code
+ // Here we just retrieve the payload size
+ return position;
+ }
}
else {
// In case of the Old RCU trailer format
// we have to read just the size of altro payload
// in units of 40-bit words
- Int_t index = fRawReader->GetDataSize();
- Int_t position = Get32bitWord(index);
+ Int_t position = (Int_t)word;
fRCUId = -1;
fRCUTrailerSize = 0;
if (!fIsShortDataHeader) {
// Check the consistency of the header and trailer
- if ((fRawReader->GetDataSize() - 4) != position) {
+ if (((fRawReader->GetDataSize() - 4) < position) ||
+ ((fRawReader->GetDataSize() - 4) >= (position + 4))) {
fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
fRawReader->GetDataSize()-4,
position));
else {
// Check the consistency of the header and trailer
// In this case the header is shorter by 4 bytes
- if (fRawReader->GetDataSize() != position) {
+ if ((fRawReader->GetDataSize() < position) ||
+ (fRawReader->GetDataSize() >= (position + 4))) {
fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
fRawReader->GetDataSize(),
position));
return word;
}
+//_____________________________________________________________________________
+Int_t AliAltroRawStream::ReadRCUTrailer(Int_t &index, Int_t trailerSize)
+{
+ // The method decodes the RCU trailer data
+ // according to the RCU fw ver.2 specs
+
+ fRCUTrailerSize = trailerSize*4;
+
+ for (trailerSize -= 2; trailerSize > 0; trailerSize--) {
+ Int_t word = Get32bitWord(index);
+ Int_t parCode = word >> 26;
+ Int_t parData = word & 0x3FFFFFF;
+ switch (parCode) {
+ case 1:
+ // ERR_REG1
+ fFECERRA = ((parData >> 13) & 0x1FFF) << 7;
+ fFECERRB = ((parData & 0x1FFF)) << 7;
+ break;
+ case 2:
+ // ERR_REG2
+ fERRREG2 = parData & 0x1FF;
+ break;
+ case 3:
+ // ERR_REG3
+ fERRREG3 = parData & 0xFFF;
+ break;
+ case 4:
+ // ERR_REG4
+ fERRREG4 = parData & 0xFFF;
+ break;
+ case 5:
+ // FEC_RO_A
+ fActiveFECsA = parData & 0xFFFF;
+ break;
+ case 6:
+ // FEC_RO_B
+ fActiveFECsB = parData & 0xFFFF;
+ break;
+ case 7:
+ // RDO_CFG1
+ fAltroCFG1 = parData & 0xFFFFF;
+ break;
+ case 8:
+ // RDO_CFG2
+ fAltroCFG2 = parData & 0x1FFFFFF;
+ break;
+ default:
+ fRawReader->AddMinorErrorLog(kRCUTrailerErr,"undef word");
+ AliWarning(Form("Undefined parameter code %d, ignore it !",
+ parCode));
+ break;
+ }
+ }
+
+ if (index < 4) {
+ fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d raw=%d bytes",
+ fRCUTrailerSize,
+ fRawReader->GetDataSize()));
+ AliWarning(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
+ fRCUTrailerSize,
+ fRawReader->GetDataSize()));
+ }
+ fRCUTrailerData = fData + index;
+
+ Int_t position = Get32bitWord(index);
+
+
+ return position;
+}
+
+//_____________________________________________________________________________
+Double_t AliAltroRawStream::GetTSample() const
+{
+ // Returns the sampling time
+ // in seconds. In case the rcu trailer
+ // was note read, return an invalid number (0)
+
+ if (!fRCUTrailerData) return 0.;
+
+ const Double_t kLHCTimeSample = 25.0e-9; // LHC clocks runs at 40 MHz
+ UChar_t fq = (fAltroCFG2 >> 5) & 0xF;
+ Double_t tSample;
+ switch (fq) {
+ case 0:
+ // 20 MHz
+ tSample = 2.0*kLHCTimeSample;
+ break;
+ case 1:
+ // 10 Mhz
+ tSample = 4.0*kLHCTimeSample;
+ break;
+ case 2:
+ // 5 MHz
+ tSample = 8.0*kLHCTimeSample;
+ break;
+ default:
+ AliWarning(Form("Invalid sampling frequency value %d !",
+ fq));
+ tSample = 0.;
+ break;
+ }
+
+ return tSample;
+}
+
+//_____________________________________________________________________________
+Double_t AliAltroRawStream::GetL1Phase() const
+{
+ // Returns the L1 phase w.r.t to the
+ // LHC clock
+ if (!fRCUTrailerData) return 0.;
+
+ const Double_t kLHCTimeSample = 25.0e-9; // LHC clocks runs at 40 MHz
+ Double_t phase = ((Double_t)(fAltroCFG2 & 0x1F))*kLHCTimeSample;
+
+ Double_t tSample = GetTSample();
+ if (phase >= tSample) {
+ AliWarning(Form("Invalid L1 trigger phase (%f >= %f) !",
+ phase,tSample));
+ phase = 0.;
+ }
+
+ return phase;
+}
+
+//_____________________________________________________________________________
+void AliAltroRawStream::PrintRCUTrailer() const
+{
+ // Prints the contents of
+ // the RCU trailer data
+ printf("RCU trailer:\n===========\n");
+ printf("FECERRA: 0x%x\nFECERRB: 0x%x\n",fFECERRA,fFECERRB);
+ printf("ERRREG2: 0x%x\n",fERRREG2);
+ printf("#channels skipped due to address mismatch: %d\n",GetNChAddrMismatch());
+ printf("#channels skipped due to bad block length: %d\n",GetNChLengthMismatch());
+ printf("Active FECs (branch A): 0x%x\nActive FECs (branch B): 0x%x\n",fActiveFECsA,fActiveFECsB);
+ printf("Baseline corr: 0x%x\n",GetBaselineCorr());
+ printf("Number of presamples: %d\nNumber of postsamples: %d\n",GetNPresamples(),GetNPostsamples());
+ printf("Second baseline corr: %d\n",GetSecondBaselineCorr());
+ printf("GlitchFilter: %d\n",GetGlitchFilter());
+ printf("Number of non-ZS postsamples: %d\nNumber of non-ZS presamples: %d\n",GetNNonZSPostsamples(),GetNNonZSPresamples());
+ printf("Number of ALTRO buffers: %d\n",GetNAltroBuffers());
+ printf("Number of pretrigger samples: %d\n",GetNPretriggerSamples());
+ printf("Number of samples per channel: %d\n",GetNSamplesPerCh());
+ printf("Sparse readout: %d\n",GetSparseRO());
+ printf("Sampling time: %e s\n",GetTSample());
+ printf("L1 Phase: %e s\n",GetL1Phase());
+ printf("AltroCFG1: 0x%x\nAltroCFG2: 0x%x\n",GetAltroCFG1(),GetAltroCFG2());
+ printf("===========\n");
+}
+
//_____________________________________________________________________________
Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
{
if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);
}
+
+//_____________________________________________________________________________
+Int_t AliAltroRawStream::GetRCUPayloadSizeInSOD() const
+{
+ // Get the size of the RCU data in case
+ // of SOD events
+ if (fRawReader) {
+ if (fRawReader->GetType() == AliRawEventHeaderBase::kStartOfData) {
+ return fPosition;
+ }
+ }
+ return -1;
+}