#include "AliAltroBuffer.h"
#include "AliAltroMapping.h"
#include "AliRawDataHeaderSim.h"
#include "AliLog.h"
#include "AliFstream.h"
ClassImp(AliAltroBuffer)
AliAltroBuffer::AliAltroBuffer(const char* fileName, AliAltroMapping *mapping):
fShift(0),
fCurrentCell(0),
fFreeCellBuffer(16),
fVerbose(0),
fFile(NULL),
fDataHeaderPos(0),
fMapping(mapping)
{
for (Int_t i = 0; i < 5; i++) fBuffer[i] = 0;
fFile = new AliFstream(fileName);
}
AliAltroBuffer::~AliAltroBuffer()
{
Flush();
if (fVerbose) Info("~AliAltroBuffer", "File Created");
delete fFile;
}
AliAltroBuffer::AliAltroBuffer(const AliAltroBuffer& source):
TObject(source),
fShift(source.fShift),
fCurrentCell(source.fCurrentCell),
fFreeCellBuffer(source.fFreeCellBuffer),
fVerbose(source.fVerbose),
fFile(NULL),
fDataHeaderPos(source.fDataHeaderPos),
fMapping(source.fMapping)
{
Fatal("AliAltroBuffer", "copy constructor not implemented");
}
AliAltroBuffer& AliAltroBuffer::operator = (const AliAltroBuffer& )
{
Fatal("operator =", "assignment operator not implemented");
return *this;
}
void AliAltroBuffer::Flush()
{
if (fFreeCellBuffer != 16) {
Int_t temp = fFreeCellBuffer;
for (Int_t i = 0; i < temp; i++){
FillBuffer(0x2AA);
}
}
}
void AliAltroBuffer::FillBuffer(Int_t val)
{
if ((val > 0x3FF) || (val < 0)) {
Error("FillBuffer", "Value out of range (10 bits): %d", val);
val = 0x3FF;
}
fFreeCellBuffer--;
fBuffer[fCurrentCell] |= (val << fShift);
fShift += 10;
if (fShift > 32) {
fCurrentCell++;
fShift -= 32;
fBuffer[fCurrentCell] |= (val >> (10 - fShift));
}
if (fShift == 32) {
fFile->WriteBuffer((char*)fBuffer, sizeof(UInt_t)*5);
for (Int_t j = 0; j < 5; j++) fBuffer[j] = 0;
fShift = 0;
fCurrentCell = 0;
fFreeCellBuffer = 16;
}
}
void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Int_t padNumber,
Int_t rowNumber, Int_t secNumber)
{
if (!fMapping) {
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)
{
Int_t num = fFreeCellBuffer % 4;
for(Int_t i = 0; i < num; i++) {
FillBuffer(0x2AA);
}
Int_t temp;
temp = hwAddress & 0x3FF;
FillBuffer(temp);
temp = (wordsNumber << 6) & 0x3FF;
temp |= (0xA << 2);
temp |= ((hwAddress >> 10) & 0x3);
FillBuffer(temp);
temp = 0xA << 6;
temp |= ((wordsNumber & 0x3FF) >> 4);
FillBuffer(temp);
temp = 0x2AA;
FillBuffer(temp);
}
void AliAltroBuffer::WriteChannel(Int_t padNumber, Int_t rowNumber,
Int_t secNumber,
Int_t nTimeBins, const Int_t* adcValues,
Int_t threshold)
{
Int_t nWords = WriteBunch(nTimeBins,adcValues,threshold);
if (nWords) WriteTrailer(nWords, padNumber, rowNumber, secNumber);
}
void AliAltroBuffer::WriteChannel(Short_t hwAddress,
Int_t nTimeBins, const Int_t* adcValues,
Int_t threshold)
{
Int_t nWords = WriteBunch(nTimeBins,adcValues,threshold);
if (nWords) WriteTrailer(nWords, hwAddress);
}
Int_t AliAltroBuffer::WriteBunch(Int_t nTimeBins, const Int_t* adcValues,
Int_t threshold)
{
Int_t nWords = 0;
Int_t timeBin = -1;
Int_t bunchLength = 0;
for (Int_t iTime = 0; iTime < nTimeBins; iTime++) {
if (adcValues[iTime] >= threshold) {
FillBuffer(adcValues[iTime]);
nWords++;
timeBin = iTime;
bunchLength++;
} else if (timeBin >= 0) {
FillBuffer(timeBin);
FillBuffer(bunchLength + 2);
nWords += 2;
timeBin = -1;
bunchLength = 0;
}
}
if (timeBin >= 0) {
FillBuffer(timeBin);
FillBuffer(bunchLength + 2);
nWords += 2;
}
return nWords;
}
void AliAltroBuffer::WriteDataHeader(Bool_t dummy, Bool_t )
{
AliRawDataHeaderSim header;
if (dummy) {
fDataHeaderPos = fFile->Tellp();
fFile->WriteBuffer((char*)(&header), sizeof(header));
} else {
UChar_t rcuVer = WriteRCUTrailer(0);
UInt_t currentFilePos = fFile->Tellp();
fFile->Seekp(fDataHeaderPos);
header.fSize = 0xFFFFFFFF;
header.fAttributesSubDetectors |= (rcuVer << 24);
fFile->WriteBuffer((char*)(&header), sizeof(header));
fFile->Seekp(currentFilePos);
}
}
UChar_t AliAltroBuffer::WriteRCUTrailer(Int_t rcuId)
{
UInt_t currentFilePos = fFile->Tellp();
UInt_t size = currentFilePos-fDataHeaderPos;
size -= sizeof(AliRawDataHeaderV3);
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;
}
size /= 5;
fFile->WriteBuffer((char *)(&size),sizeof(UInt_t));
UInt_t buffer = (2 & 0x7F);
buffer |= ((rcuId & 0x1FF) << 7);
buffer |= 0xAAAAU << 16;
fFile->WriteBuffer((char *)(&buffer),sizeof(UInt_t));
return 0;
}