// to read and write digits
// To be used in Alice Data Challenges
// and in the compression of the RAW data
-// Author: D.Favretto
#include "AliAltroBuffer.h"
#include "AliAltroMapping.h"
-#include "AliRawDataHeader.h"
+#include "AliRawDataHeaderSim.h"
#include "AliLog.h"
-#include <Riostream.h>
-#include <stdlib.h>
+#include "AliFstream.h"
+//#include <stdlib.h>
ClassImp(AliAltroBuffer)
//_____________________________________________________________________________
-AliAltroBuffer::AliAltroBuffer(const char* fileName, Int_t flag, const AliAltroMapping *mapping):
+AliAltroBuffer::AliAltroBuffer(const char* fileName, AliAltroMapping *mapping):
fShift(0),
fCurrentCell(0),
- fFreeCellBuffer(0),
- fFlag(flag),
+ fFreeCellBuffer(16),
fVerbose(0),
fFile(NULL),
- fMaskBackward(0xFF),
- fFilePosition(0),
- fFileEnd(0),
fDataHeaderPos(0),
- fEndingFillWords(0),
fMapping(mapping)
{
-//if flag = 1 the actual object is used in the write mode
-//if flag = 0 the actual object is used in the read mode
-
//the buffer is cleaned
for (Int_t i = 0; i < 5; i++) fBuffer[i] = 0;
- if (flag) {
- fFreeCellBuffer = 16;
- fShift = 32;
- //open the output file
-#ifndef __DECCXX
- fFile = new fstream(fileName, ios::binary|ios::out);
-#else
- fFile = new fstream(fileName, ios::out);
-#endif
- } else {
- //open the input file
-#ifndef __DECCXX
- fFile = new fstream(fileName, ios::binary|ios::in);
-#else
- fFile = new fstream(fileName, ios::in);
-#endif
- if (!fFile) {
- Error("AliAltroBuffer", "File doesn't exist: %s", fileName);
- return;
- }
- fShift = 0;
- //To get the file dimension (position of the last element in term of bytes)
- fFile->seekg(0, ios::end);
- fFilePosition = fFile->tellg();
- fFileEnd = fFilePosition;
- fFile->seekg(0);
- }
+ //open the output file
+ fFile = new AliFstream(fileName);
}
{
// destructor
- if (fFlag) {
- //Flush out the Buffer content at the end only if Buffer wasn't completely filled
- Flush();
- if (fVerbose) Info("~AliAltroBuffer", "File Created");
- }//end if
- fFile->close();
+ //Flush out the Buffer content at the end only if Buffer wasn't completely filled
+ Flush();
+ if (fVerbose) Info("~AliAltroBuffer", "File Created");
+
delete fFile;
}
fShift(source.fShift),
fCurrentCell(source.fCurrentCell),
fFreeCellBuffer(source.fFreeCellBuffer),
- fFlag(source.fFlag),
fVerbose(source.fVerbose),
fFile(NULL),
- fMaskBackward(source.fMaskBackward),
- fFilePosition(source.fFilePosition),
- fFileEnd(source.fFileEnd),
fDataHeaderPos(source.fDataHeaderPos),
- fEndingFillWords(source.fEndingFillWords),
fMapping(source.fMapping)
{
// Copy Constructor
return *this;
}
-
-//_____________________________________________________________________________
-Int_t AliAltroBuffer::GetNext()
-{
-//It reads a 10 bits word in forward dicection from the Buffer.
-//A new Buffer is read from the file only when Buffer is empty.
-//If there aren't elements anymore -1 is returned otherwise
-//the next element is returned
-
- UInt_t mask = 0xFFC00000;
- UInt_t temp;
- UInt_t value;
- if (!fShift) {
- if (fFile->tellg() >= (Int_t)fFileEnd) return -1;
- if (fFile->read((char*)fBuffer, sizeof(UInt_t)*5)) {
- fCurrentCell = 0;
- fShift = 22;
- value = fBuffer[fCurrentCell] & mask;
- value = value >> 22;
- fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << 10;
- return value;
- } else {
- return -1;
- }
- } else {
- if (fShift >= 10) {
- value = fBuffer[fCurrentCell] & mask;
- value = value >> 22;
- fShift -= 10;
- fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << 10;
- } else {
- value = fBuffer[fCurrentCell] & mask;
- fCurrentCell++;
- temp = fBuffer[fCurrentCell];
- temp = temp >> fShift;
- temp = temp & mask;
- value = value | temp;
- value = value >> 22;
- fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << (10-fShift);
- fShift += 22;
- }
- return value;
- }//end else
-}
-
-//_____________________________________________________________________________
-Int_t AliAltroBuffer::GetNextBackWord()
-{
-//It reads a 10 bits word in backward dicection from the Buffer.
-//A new Buffer is read from the file only when Buffer is empty.
-//If there aren't elements anymore -1 is returned otherwise
-//the next element is returned
-
- UInt_t mask = 0x3FF;
- UInt_t temp;
- UInt_t value;
- if (!fShift) {
- if (fFilePosition > fDataHeaderPos){
- fFilePosition -= sizeof(UInt_t)*5;
- fFile->seekg(fFilePosition);
- fFile->read((char*)fBuffer, sizeof(UInt_t)*5);
-
- fCurrentCell = 4;
- fShift = 22;
- fMaskBackward = 0xFF;
- value = fBuffer[fCurrentCell] & mask;
- fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> 10;
- return value;
- } else {
- fFile->seekg(fDataHeaderPos);
- return -1;
- }
- } else {
- if (fShift >= 10) {
- value = fBuffer[fCurrentCell] & mask;
- fShift -= 10;
- fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> 10;
- } else {
- value = fBuffer[fCurrentCell];
- fCurrentCell--;
- temp = fBuffer[fCurrentCell] & mask;
- temp = temp & fMaskBackward;
- fMaskBackward = fMaskBackward >> 2;
- temp = temp << fShift;
- value = value | temp;
- fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> (10-fShift);
- fShift = 22 + fShift;
- }
- return value;
- }//end else
-}
-
//_____________________________________________________________________________
void AliAltroBuffer::Flush()
{
val = 0x3FF;
}
fFreeCellBuffer--;
- if (fShift < 10) {
- Int_t temp = val;
- val = val >> (10-fShift);
- fBuffer[fCurrentCell] |= val;
+
+ fBuffer[fCurrentCell] |= (val << fShift);
+ fShift += 10;
+
+ if (fShift > 32) {
fCurrentCell++;
- fShift += 32;
- val = temp;
+ fShift -= 32;
+ fBuffer[fCurrentCell] |= (val >> (10 - fShift));
}
- fShift -= 10;
- val = val << fShift;
- fBuffer[fCurrentCell] |= val;
- if (!fShift) {
+
+ if (fShift == 32) {
//Buffer is written into a file
- fFile->write((char*)fBuffer, sizeof(UInt_t)*5);
+ fFile->WriteBuffer((char*)fBuffer, sizeof(UInt_t)*5);
//Buffer is empty
for (Int_t j = 0; j < 5; j++) fBuffer[j] = 0;
- fShift = 32;
+ fShift = 0;
fCurrentCell = 0;
fFreeCellBuffer = 16;
}
}
-
-//_____________________________________________________________________________
-void AliAltroBuffer::WriteDummyTrailer(Int_t wordsNumber, Int_t padNumber,
- Int_t rowNumber, Int_t secNumber)
-{
-//Writes a trailer of 40 bits
-
- Int_t num = fFreeCellBuffer % 4;
- for(Int_t i = 0; i < num; i++) {
- FillBuffer(0x2AA);
- }//end for
- FillBuffer(wordsNumber);
- FillBuffer(padNumber);
- FillBuffer(rowNumber);
- FillBuffer(secNumber);
-}
-
//_____________________________________________________________________________
void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Int_t padNumber,
Int_t rowNumber, Int_t secNumber)
//Writes a trailer of 40 bits
if (!fMapping) {
- AliError("No ALTRO mapping information is loaded! Filling a dummy trailer!");
- return WriteDummyTrailer(wordsNumber,padNumber,
- rowNumber,secNumber);
+ AliFatal("No ALTRO mapping information is loaded!");
}
+ Short_t hwAddress = fMapping->GetHWAddress(rowNumber,padNumber,secNumber);
+ if (hwAddress == -1)
+ AliFatal(Form("No hardware (ALTRO) adress found for these pad-row (%d) and pad (%d) indeces !",rowNumber,padNumber));
+ WriteTrailer(wordsNumber,hwAddress);
+}
+
+//_____________________________________________________________________________
+void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Short_t hwAddress)
+{
+//Writes a trailer of 40 bits using
+//a given hardware adress
Int_t num = fFreeCellBuffer % 4;
for(Int_t i = 0; i < num; i++) {
FillBuffer(0x2AA);
}//end for
Int_t temp;
- temp = 0x2AA;
- FillBuffer(temp);
- temp = 0xA << 6;
- temp |= (wordsNumber >> 4);
+ temp = hwAddress & 0x3FF;
FillBuffer(temp);
+
temp = (wordsNumber << 6) & 0x3FF;
temp |= (0xA << 2);
+ temp |= ((hwAddress >> 10) & 0x3);
+ FillBuffer(temp);
- Short_t hwAdress = fMapping->GetHWAdress(rowNumber,padNumber);
- if (hwAdress == -1)
- AliFatal(Form("No hardware (ALTRO) adress found for these pad-row (%d) and pad (%d) indeces !",rowNumber,padNumber));
-
- temp |= (hwAdress >> 10) & 0x3;
+ temp = 0xA << 6;
+ temp |= ((wordsNumber & 0x3FF) >> 4);
FillBuffer(temp);
- temp = hwAdress & 0x3FF;
+
+ temp = 0x2AA;
FillBuffer(temp);
}
//_____________________________________________________________________________
-Bool_t AliAltroBuffer::ReadTrailer(Int_t& wordsNumber, Int_t& padNumber,
- Int_t& rowNumber, Int_t& secNumber)
+void AliAltroBuffer::WriteChannel(Int_t padNumber, Int_t rowNumber,
+ Int_t secNumber,
+ Int_t nTimeBins, const Int_t* adcValues,
+ Int_t threshold)
{
-//Read a trailer of 40 bits in the forward reading mode
-
- wordsNumber = GetNext();
- if (wordsNumber == -1) return kFALSE;
- padNumber = GetNext();
- if (padNumber == -1) return kFALSE;
- rowNumber = GetNext();
- if (rowNumber == -1) return kFALSE;
- secNumber = GetNext();
- if (secNumber == -1) return kFALSE;
- return kTRUE;
+ //Write all ADC values and the trailer of a channel
+ Int_t nWords = WriteBunch(nTimeBins,adcValues,threshold);
+ // write the trailer
+ if (nWords) WriteTrailer(nWords, padNumber, rowNumber, secNumber);
}
//_____________________________________________________________________________
-Bool_t AliAltroBuffer::ReadTrailerBackward(Int_t& wordsNumber,
- Int_t& padNumber,
- Int_t& rowNumber, Int_t& secNumber)
+void AliAltroBuffer::WriteChannel(Short_t hwAddress,
+ Int_t nTimeBins, const Int_t* adcValues,
+ Int_t threshold)
{
-//Read a trailer of 40 bits in the backward reading mode
-
- Int_t temp;
- fEndingFillWords = 0;
- do {
- temp = GetNextBackWord();
- fEndingFillWords++;
- if (temp == -1) return kFALSE;
- } while (temp == 0x2AA);
- fEndingFillWords--;
- secNumber = temp;
- rowNumber = GetNextBackWord();
- if (rowNumber == -1) return kFALSE;
- padNumber = GetNextBackWord();
- if (padNumber == -1) return kFALSE;
- wordsNumber = GetNextBackWord();
- if (wordsNumber == -1) return kFALSE;
- return kTRUE;
-}
-
+ //Write all ADC values and the trailer of a channel
+ Int_t nWords = WriteBunch(nTimeBins,adcValues,threshold);
+ // write the trailer
+ if (nWords) WriteTrailer(nWords, hwAddress);
+}
//_____________________________________________________________________________
-void AliAltroBuffer::WriteChannel(Int_t padNumber, Int_t rowNumber,
- Int_t secNumber,
- Int_t nTimeBins, const Int_t* adcValues,
- Int_t threshold)
+Int_t AliAltroBuffer::WriteBunch(Int_t nTimeBins, const Int_t* adcValues,
+ Int_t threshold)
{
-//Write all ADC values and the trailer of a channel
+ //Write all ADC values
+ //Return number of words written
Int_t nWords = 0;
Int_t timeBin = -1;
nWords += 2;
}
- // write the trailer
- WriteTrailer(nWords, padNumber, rowNumber, secNumber);
+ return nWords;
}
-
//_____________________________________________________________________________
-void AliAltroBuffer::WriteDataHeader(Bool_t dummy, Bool_t compressed)
+void AliAltroBuffer::WriteDataHeader(Bool_t dummy, Bool_t /*compressed*/)
{
//Write a (dummy or real) DDL data header,
-//set the compression bit if compressed
+//set the attributes according to the RCU version
- AliRawDataHeader header;
+ AliRawDataHeaderSim header;
if (dummy) {
//if size=0 it means that this data header is a dummy data header
- fDataHeaderPos = fFile->tellp();
- fFile->write((char*)(&header), sizeof(header));
+ fDataHeaderPos = fFile->Tellp();
+ fFile->WriteBuffer((char*)(&header), sizeof(header));
} else {
- UInt_t currentFilePos = fFile->tellp();
- fFile->seekp(fDataHeaderPos);
- header.fSize = currentFilePos-fDataHeaderPos;
- header.SetAttribute(0); // valid data
- if (compressed) header.SetAttribute(1);
- fFile->write((char*)(&header), sizeof(header));
- fFile->seekp(currentFilePos);
+ UChar_t rcuVer = WriteRCUTrailer(0);
+ UInt_t currentFilePos = fFile->Tellp();
+ fFile->Seekp(fDataHeaderPos);
+ header.fSize = 0xFFFFFFFF; // RCU can't write raw-data size so we always get an 'invalid' size field
+ header.fAttributesSubDetectors |= (rcuVer << 24);
+ fFile->WriteBuffer((char*)(&header), sizeof(header));
+ fFile->Seekp(currentFilePos);
}
}
//_____________________________________________________________________________
-Bool_t AliAltroBuffer::ReadDataHeader()
+UChar_t AliAltroBuffer::WriteRCUTrailer(Int_t rcuId)
{
-//Read the DDL data header at the beginning of the file,
-//returns true in case of valid data
-
- AliRawDataHeader header;
- UInt_t currentPos = fFile->tellp();
- fFile->seekp(0);
- if (!fFile->read((char*)(&header), sizeof(header))) return kFALSE;
- fDataHeaderPos = fFile->tellp();
- fFile->seekp(currentPos);
- return header.TestAttribute(0);
-}
+ // Writes the RCU trailer
+ // rcuId the is serial number of the corresponding
+ // RCU. The basic format of the trailer can be
+ // found in the RCU manual.
+ // This method should be called at the end of
+ // raw data writing.
+
+ UInt_t currentFilePos = fFile->Tellp();
+ UInt_t size = currentFilePos-fDataHeaderPos;
+ size -= sizeof(AliRawDataHeader);
+
+ if ((size % 5) != 0) {
+ AliFatal(Form("The current raw data payload is not a mutiple of 5 (%d) ! Can not write the RCU trailer !",size));
+ return 0;
+ }
+ // Now put the size in unit of number of 40bit words
+ size /= 5;
+ fFile->WriteBuffer((char *)(&size),sizeof(UInt_t));
+
+ // Now several not yet full defined fields
+ // In principle they are supposed to contain
+ // information about the sampling frequency,
+ // L1 phase, list of 'dead' FECs, etc.
+ // UInt_t buffer[n];
+ // fFile->WriteBuffer((char *)(buffer),sizeof(UInt_t)*n);
+
+ // Now the RCU identifier and size of the trailer
+ // FOr the moment the triler size is 2 32-bit words
+ UInt_t buffer = (2 & 0x7F);
+ buffer |= ((rcuId & 0x1FF) << 7);
+ buffer |= 0xAAAAU << 16;
+ fFile->WriteBuffer((char *)(&buffer),sizeof(UInt_t));
+
+ return 0;
+}