#include "AliAltroRawStream.h"
#include "AliRawReader.h"
+#include "AliLog.h"
ClassImp(AliAltroRawStream)
//_____________________________________________________________________________
AliAltroRawStream::AliAltroRawStream(AliRawReader* rawReader) :
- fSector(-1),
- fPrevSector(-1),
- fRow(-1),
- fPrevRow(-1),
- fPad(-1),
- fPrevPad(-1),
+ 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(rawReader),
fData(NULL),
fPosition(0),
fCount(0),
- fBunchLength(0)
+ fBunchLength(0),
+ fRCUTrailerData(NULL),
+ fRCUTrailerSize(0)
{
// create an object to read Altro raw digits
-
+ fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
}
//_____________________________________________________________________________
AliAltroRawStream::AliAltroRawStream(const AliAltroRawStream& stream) :
TObject(stream),
- fSector(-1),
- fPrevSector(-1),
- fRow(-1),
- fPrevRow(-1),
- fPad(-1),
- fPrevPad(-1),
- fTime(-1),
- fSignal(-1),
- fRawReader(NULL),
- fData(NULL),
- fPosition(0),
- fCount(0),
- fBunchLength(0)
+ fNoAltroMapping(stream.fNoAltroMapping),
+ fIsOldRCUFormat(stream.fIsOldRCUFormat),
+ 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),
+ fBunchLength(stream.fBunchLength),
+ fRCUTrailerData(stream.fRCUTrailerData),
+ fRCUTrailerSize(stream.fRCUTrailerSize)
{
- Fatal("AliAltroRawStream", "copy constructor not implemented");
+ fSegmentation[0] = stream.fSegmentation[0];
+ fSegmentation[1] = stream.fSegmentation[1];
+ fSegmentation[2] = stream.fSegmentation[2];
}
//_____________________________________________________________________________
-AliAltroRawStream& AliAltroRawStream::operator = (const AliAltroRawStream&
- /* stream */)
+AliAltroRawStream& AliAltroRawStream::operator = (const AliAltroRawStream& stream)
{
- Fatal("operator =", "assignment operator not implemented");
+ if(&stream == this) return *this;
+
+ fNoAltroMapping = stream.fNoAltroMapping;
+ fIsOldRCUFormat = stream.fIsOldRCUFormat;
+ 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;
+ fBunchLength = stream.fBunchLength;
+ fRCUTrailerData = stream.fRCUTrailerData;
+ fRCUTrailerSize = stream.fRCUTrailerSize;
+
+ fSegmentation[0] = stream.fSegmentation[0];
+ fSegmentation[1] = stream.fSegmentation[1];
+ fSegmentation[2] = stream.fSegmentation[2];
+
return *this;
}
}
+//_____________________________________________________________________________
+void AliAltroRawStream::Reset()
+{
+// reset altro raw stream params
+
+ fPosition = fCount = fBunchLength = 0;
+
+ fRCUTrailerData = NULL;
+ fRCUTrailerSize = 0;
+
+ fDDLNumber = fPrevDDLNumber = fRCUId = fPrevRCUId = fHWAddress = fPrevHWAddress = fTime = fPrevTime = fSignal = fTimeBunch = -1;
+
+ if (fRawReader) fRawReader->Reset();
+
+ fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
+}
//_____________________________________________________________________________
Bool_t AliAltroRawStream::Next()
// read the next raw digit
// returns kFALSE if there is no digit left
- fPrevSector = fSector;
- fPrevRow = fRow;
- fPrevPad = fPad;
+ fPrevDDLNumber = fDDLNumber;
+ fPrevRCUId = fRCUId;
+ fPrevHWAddress = fHWAddress;
+ fPrevTime = fTime;
while (fCount == 0) { // next trailer
if (fPosition <= 0) { // next payload
if (!fRawReader->ReadNextData(fData)) return kFALSE;
} while (fRawReader->GetDataSize() == 0);
- fPosition = (fRawReader->GetDataSize() * 8) / 10;
- while (Get10BitWord(fData, fPosition-1) == 0x2AA) fPosition--;
+ fDDLNumber = fRawReader->GetDDLID();
+
+ fPosition = GetPosition();
}
- if (fPosition > 0) {
- // read the trailer
- if (fPosition <= 4) {
- Error("Next", "could not read trailer");
- return kFALSE;
- }
- fSector = Get10BitWord(fData, --fPosition);
- fRow = Get10BitWord(fData, --fPosition);
- fPad = Get10BitWord(fData, --fPosition);
- fCount = Get10BitWord(fData, --fPosition);
+ ReadTrailer();
- fPosition -= (4 - (fCount % 4)) % 4; // skip fill words
- fBunchLength = 0;
- }
+ fBunchLength = 0;
}
- if (fBunchLength == 0) {
- if (fPosition <= 0) {
- Error("Next", "could not read bunch length");
- return kFALSE;
- }
- fBunchLength = Get10BitWord(fData, --fPosition) - 2;
- fTimeBunch = fBunchLength;
- fCount--;
+ if (fBunchLength == 0) ReadBunch();
+ else fTime--;
+
+ ReadAmplitude();
+
+ return kTRUE;
+}
+
+//_____________________________________________________________________________
+void AliAltroRawStream::SelectRawData(Int_t detId)
+{
+ // Select the raw data for specific
+ // detector id
+ AliDebug(1,Form("Selecting raw data for detector %d",detId));
+ fRawReader->Select(detId);
+}
- if (fPosition <= 0) {
- Error("Next", "could not read time bin");
+//_____________________________________________________________________________
+void AliAltroRawStream::SelectRawData(const char *detName)
+{
+ // Select the raw data for specific
+ // detector name
+ AliDebug(1,Form("Selecting raw data for detector %s",detName));
+ fRawReader->Select(detName);
+}
+
+//_____________________________________________________________________________
+UShort_t AliAltroRawStream::GetNextWord()
+{
+ // Read the next 10 bit word in backward direction
+ // The input stream access is given by fData and fPosition
+
+ fPosition--;
+
+ Int_t iBit = fPosition * 10;
+ Int_t iByte = iBit / 8;
+ Int_t shift = iBit % 8;
+
+ // the raw data is written as integers where the low bits are filled first
+ // -> little endian is assumed here !
+ Int_t iByteLow = iByte;
+ iByte++;
+ Int_t iByteHigh = iByte;
+ return ((fData[iByteHigh] * 256 + fData[iByteLow]) >> shift) & 0x03FF;
+}
+
+//_____________________________________________________________________________
+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;
+ while ((temp = GetNextWord()) == 0x2AA) nFillWords++;
+ if (nFillWords == 0) {
+ fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0x2AA");
+ // PrintDebug();
+ AliWarning("Incorrect trailer found ! Expected 0x2AA not found !");
+ // trying to recover and find the next bunch
+ while ((fPosition > 5) && (temp != 0x2AA)) temp = GetNextWord();
+ if (temp != 0x2AA) {
+ fCount = fPosition = 0;
return kFALSE;
}
- fTime = Get10BitWord(fData, --fPosition);
- fCount--;
- } else {
- fTime--;
+ temp = GetNextWord();
}
- if (fPosition <= 0) {
- Error("Next", "could not read sample amplitude");
+ //Then read the trailer
+ if (fPosition < 5) {
+ fRawReader->AddMajorErrorLog(kAltroTrailerErr,Form("size %d < 5",
+ fPosition));
+ // PrintDebug();
+ AliWarning(Form("Incorrect raw data size ! Expected at least 5 words but found %d !",fPosition));
+ fCount = fPosition = 0;
return kFALSE;
}
- fSignal = Get10BitWord(fData, --fPosition);
+
+ fCount = (temp << 4) & 0x3FF;
+ if ((temp >> 6) != 0xA) {
+ fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0xA");
+ // PrintDebug();
+ AliWarning(Form("Incorrect trailer found ! Expecting 0xA but found 0x%x !",temp >> 6));
+ fCount = 0;
+ return kFALSE;
+ }
+
+ temp = GetNextWord();
+ fHWAddress = (temp & 0x3) << 10;
+ if (((temp >> 2) & 0xF) != 0xA) {
+ fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no second 0xA");
+ // PrintDebug();
+ AliWarning(Form("Incorrect trailer found ! Expecting second 0xA but found 0x%x !",(temp >> 2) & 0xF));
+ fCount = 0;
+ return kFALSE;
+ }
+ fCount |= ((temp & 0x3FF) >> 6);
+ if (fCount == 0) return kFALSE;
+ 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;
+
+ fPosition -= (4 - (fCount % 4)) % 4; // skip fill words
+
+ 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 (fCount <= 2) {
+ fRawReader->AddMinorErrorLog(kBunchLengthReadErr,"");
+ // PrintDebug();
+ 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;
+ if (fBunchLength > fCount) {
+ fRawReader->AddMinorErrorLog(kBunchLengthReadErr,Form("bl=%d",fBunchLength));
+ // PrintDebug();
+ AliWarning(Form("Could not read bunch length ! Bunch length = %d (>%d)",fBunchLength,fCount));
+ fBunchLength = fTimeBunch = fCount = 0;
+ return;
+ }
+ fTimeBunch = fBunchLength;
+ fCount--;
+
+ fTime = GetNextWord();
+ fCount--;
+
+ return;
+}
+
+//_____________________________________________________________________________
+void AliAltroRawStream::ReadAmplitude()
+{
+ // Read next time bin amplitude
+ if (fCount <= 0) {
+ fRawReader->AddMinorErrorLog(kAmplitudeReadErr,"");
+ // PrintDebug();
+ AliWarning("Could not read sample amplitude !");
+ fCount = fSignal = fBunchLength = 0;
+ return;
+ }
+
+ fSignal = GetNextWord();
+
fCount--;
fBunchLength--;
+ return;
+}
+
+//_____________________________________________________________________________
+Int_t AliAltroRawStream::GetPosition()
+{
+ // Sets the position in the
+ // input stream
+ // Read the RCU trailer
+ // This includes the trailer size,
+ // RCU identifier and raw data payload.
+ // 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);
+
+ // Now read the beginning of the trailer
+ // where the payload size is written
+ if (trailerSize < 2) {
+ fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes",
+ trailerSize*4));
+ AliWarning(Form("Invalid trailer size found (%d bytes) !",
+ trailerSize*4));
+ }
+ fRCUTrailerSize = (trailerSize-2)*4;
+ index -= fRCUTrailerSize;
+ if (index < 4) {
+ fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d raw=%d bytes",
+ trailerSize*4,
+ fRawReader->GetDataSize()));
+ AliWarning(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
+ trailerSize*4,
+ fRawReader->GetDataSize()));
+ }
+ 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) ||
+ ((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;
+ }
+ 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);
+
+ fRCUId = -1;
+ fRCUTrailerSize = 0;
+ fRCUTrailerData = NULL;
+
+ // The size is specified in a number of 40bits
+ // Therefore we need to transform it to number of bytes
+ position *= 5;
+
+ if (!fIsShortDataHeader) {
+
+ // Check the consistency of the header and trailer
+ if (((fRawReader->GetDataSize() - 4) < position) ||
+ ((fRawReader->GetDataSize() - 4) >= (position + 4))) {
+ fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
+ fRawReader->GetDataSize()-4,
+ position));
+ // PrintDebug();
+ AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
+ fRawReader->GetDataSize()-4,
+ position));
+ position = fRawReader->GetDataSize()-4;
+ }
+ }
+ else {
+ // Check the consistency of the header and trailer
+ // In this case the header is shorter by 4 bytes
+ if ((fRawReader->GetDataSize() < position) ||
+ (fRawReader->GetDataSize() >= (position + 4))) {
+ fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
+ fRawReader->GetDataSize(),
+ position));
+ // PrintDebug();
+ AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
+ fRawReader->GetDataSize(),
+ position));
+ position = fRawReader->GetDataSize();
+ }
+
+ // 7 32-bit words Common Data Header
+ // therefore we have to shift back by 4 bytes
+ // the pointer to the raw data payload
+ fData -= 4;
+ }
+
+ // Return the position in units of 10-bit words
+ return position*8/10;
+ }
+}
+
+//_____________________________________________________________________________
+UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
+{
+ // This method returns the 32 bit word at a given
+ // position inside the raw data payload.
+ // The 'index' points to the beginning of the next word.
+ // The method is supposed to be endian (platform)
+ // independent.
+ if (!fData) {
+ PrintDebug();
+ AliFatal("Raw data paylod buffer is not yet initialized !");
+ }
+
+ if (index < 4) {
+ fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
+ // PrintDebug();
+ AliWarning(Form("Invalid raw data payload position (%d) !",index));
+ }
+
+ UInt_t word = 0;
+ word = fData[--index] << 24;
+ word |= fData[--index] << 16;
+ word |= fData[--index] << 8;
+ word |= fData[--index];
+
+ return word;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
+{
+ // Return a pointer to the RCU trailer
+ // data. Should be called always after
+ // the RCU trailer was already processed
+ // in the GetPosition() method
+ if (!fRCUTrailerSize || !fRCUTrailerData) {
+ AliError("No valid RCU trailer data is found !");
+ data = NULL;
+ return kFALSE;
+ }
+
+ data = fRCUTrailerData;
+
return kTRUE;
}
+//_____________________________________________________________________________
+void AliAltroRawStream::PrintDebug() const
+{
+ // The method prints all the available
+ // debug information.
+ // Its is used in case of decoding errors.
+
+ AliError("Start of debug printout\n--------------------");
+
+ Dump();
+ if (fRawReader) fRawReader->Dump();
+
+ AliError("End of debug printout\n--------------------");
+}
//_____________________________________________________________________________
-UShort_t AliAltroRawStream::Get10BitWord(UChar_t* buffer, Int_t position) const
+Int_t AliAltroRawStream::GetBranch() const
{
-// return a word in a 10 bit array as an UShort_t
+ // The method provides the RCU branch index (0 or 1)
+ // for the current hardware address.
+ // In case the hardware address has not been yet
+ // initialized, the method returns -1
+ if (fHWAddress == -1) return -1;
- Int_t iBit = position * 10;
- Int_t iByte = iBit / 8;
- Int_t shift = iBit % 8;
-// return ((buffer[iByte+1] * 256 + buffer[iByte]) >> shift) & 0x03FF;
+ return ((fHWAddress >> 11) & 0x1);
+}
- // recalculate the byte numbers and the shift because
- // the raw data is written as integers where the high bits are filled first
- // -> little endian is assumed here !
- Int_t iByteHigh = 4 * (iByte / 4) + 3 - (iByte % 4);
- iByte++;
- Int_t iByteLow = 4 * (iByte / 4) + 3 - (iByte % 4);
- shift = 6 - shift;
- return ((buffer[iByteHigh] * 256 + buffer[iByteLow]) >> shift) & 0x03FF;
+//_____________________________________________________________________________
+Int_t AliAltroRawStream::GetFEC() const
+{
+ // The method provides the front-end card index
+ // for the current hardware address.
+ // In case the hardware address has not been yet
+ // initialized, the method returns -1
+ if (fHWAddress == -1) return -1;
+
+ return ((fHWAddress >> 7) & 0xF);
+}
+
+//_____________________________________________________________________________
+Int_t AliAltroRawStream::GetAltro() const
+{
+ // The method provides the altro chip index
+ // for the current hardware address.
+ // In case the hardware address has not been yet
+ // initialized, the method returns -1
+ if (fHWAddress == -1) return -1;
+
+ return ((fHWAddress >> 4) & 0x7);
+}
+
+//_____________________________________________________________________________
+Int_t AliAltroRawStream::GetChannel() const
+{
+ // The method provides the channel index
+ // for the current hardware address.
+ // In case the hardware address has not been yet
+ // initialized, the method returns -1
+ if (fHWAddress == -1) return -1;
+
+ return (fHWAddress & 0xF);
+}
+
+//_____________________________________________________________________________
+void AliAltroRawStream::AddMappingErrorLog(const char *message)
+{
+ // Signal a mapping error
+ // The method can be used by the TPC,PHOS,EMCAL,FMD raw stream
+ // classes in order to log an error related to bad altro mapping
+
+ if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);
}