1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 // Interface to the Altro format
19 // to read and write digits
20 // To be used in Alice Data Challenges
21 // and in the compression of the RAW data
24 #include "AliAltroBuffer.h"
25 #include "AliAltroMapping.h"
26 #include "AliRawDataHeader.h"
28 #include <Riostream.h>
32 ClassImp(AliAltroBuffer)
34 //_____________________________________________________________________________
35 AliAltroBuffer::AliAltroBuffer(const char* fileName, Int_t flag, const AliAltroMapping *mapping):
49 //if flag = 1 the actual object is used in the write mode
50 //if flag = 0 the actual object is used in the read mode
52 //the buffer is cleaned
53 for (Int_t i = 0; i < 5; i++) fBuffer[i] = 0;
58 //open the output file
60 fFile = new fstream(fileName, ios::binary|ios::out);
62 fFile = new fstream(fileName, ios::out);
67 fFile = new fstream(fileName, ios::binary|ios::in);
69 fFile = new fstream(fileName, ios::in);
72 Error("AliAltroBuffer", "File doesn't exist: %s", fileName);
76 //To get the file dimension (position of the last element in term of bytes)
77 fFile->seekg(0, ios::end);
78 fFilePosition = fFile->tellg();
79 fFileEnd = fFilePosition;
85 //_____________________________________________________________________________
86 AliAltroBuffer::~AliAltroBuffer()
91 //Flush out the Buffer content at the end only if Buffer wasn't completely filled
93 if (fVerbose) Info("~AliAltroBuffer", "File Created");
100 //_____________________________________________________________________________
101 AliAltroBuffer::AliAltroBuffer(const AliAltroBuffer& source):
103 fShift(source.fShift),
104 fCurrentCell(source.fCurrentCell),
105 fFreeCellBuffer(source.fFreeCellBuffer),
107 fVerbose(source.fVerbose),
109 fMaskBackward(source.fMaskBackward),
110 fFilePosition(source.fFilePosition),
111 fFileEnd(source.fFileEnd),
112 fDataHeaderPos(source.fDataHeaderPos),
113 fEndingFillWords(source.fEndingFillWords),
114 fMapping(source.fMapping)
118 Fatal("AliAltroBuffer", "copy constructor not implemented");
121 //_____________________________________________________________________________
122 AliAltroBuffer& AliAltroBuffer::operator = (const AliAltroBuffer& /*source*/)
126 Fatal("operator =", "assignment operator not implemented");
131 //_____________________________________________________________________________
132 Int_t AliAltroBuffer::GetNext()
134 //It reads a 10 bits word in forward dicection from the Buffer.
135 //A new Buffer is read from the file only when Buffer is empty.
136 //If there aren't elements anymore -1 is returned otherwise
137 //the next element is returned
139 UInt_t mask = 0xFFC00000;
143 if (fFile->tellg() >= (Int_t)fFileEnd) return -1;
144 if (fFile->read((char*)fBuffer, sizeof(UInt_t)*5)) {
147 value = fBuffer[fCurrentCell] & mask;
149 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << 10;
156 value = fBuffer[fCurrentCell] & mask;
159 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << 10;
161 value = fBuffer[fCurrentCell] & mask;
163 temp = fBuffer[fCurrentCell];
164 temp = temp >> fShift;
166 value = value | temp;
168 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << (10-fShift);
175 //_____________________________________________________________________________
176 Int_t AliAltroBuffer::GetNextBackWord()
178 //It reads a 10 bits word in backward dicection from the Buffer.
179 //A new Buffer is read from the file only when Buffer is empty.
180 //If there aren't elements anymore -1 is returned otherwise
181 //the next element is returned
187 if (fFilePosition > fDataHeaderPos){
188 fFilePosition -= sizeof(UInt_t)*5;
189 fFile->seekg(fFilePosition);
190 fFile->read((char*)fBuffer, sizeof(UInt_t)*5);
194 fMaskBackward = 0xFF;
195 value = fBuffer[fCurrentCell] & mask;
196 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> 10;
199 fFile->seekg(fDataHeaderPos);
204 value = fBuffer[fCurrentCell] & mask;
206 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> 10;
208 value = fBuffer[fCurrentCell];
210 temp = fBuffer[fCurrentCell] & mask;
211 temp = temp & fMaskBackward;
212 fMaskBackward = fMaskBackward >> 2;
213 temp = temp << fShift;
214 value = value | temp;
215 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> (10-fShift);
216 fShift = 22 + fShift;
222 //_____________________________________________________________________________
223 void AliAltroBuffer::Flush()
225 // Flushes the Buffer content
226 if (fFreeCellBuffer != 16) {
227 Int_t temp = fFreeCellBuffer;
228 for (Int_t i = 0; i < temp; i++){
234 //_____________________________________________________________________________
235 void AliAltroBuffer::FillBuffer(Int_t val)
237 //Fills the Buffer with 16 ten bits words and write into a file
239 if ((val > 0x3FF) || (val < 0)) {
240 Error("FillBuffer", "Value out of range (10 bits): %d", val);
246 val = val >> (10-fShift);
247 fBuffer[fCurrentCell] |= val;
254 fBuffer[fCurrentCell] |= val;
256 //Buffer is written into a file
257 fFile->write((char*)fBuffer, sizeof(UInt_t)*5);
259 for (Int_t j = 0; j < 5; j++) fBuffer[j] = 0;
262 fFreeCellBuffer = 16;
267 //_____________________________________________________________________________
268 void AliAltroBuffer::WriteDummyTrailer(Int_t wordsNumber, Int_t padNumber,
269 Int_t rowNumber, Int_t secNumber)
271 //Writes a trailer of 40 bits
273 Int_t num = fFreeCellBuffer % 4;
274 for(Int_t i = 0; i < num; i++) {
277 FillBuffer(wordsNumber);
278 FillBuffer(padNumber);
279 FillBuffer(rowNumber);
280 FillBuffer(secNumber);
283 //_____________________________________________________________________________
284 void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Int_t padNumber,
285 Int_t rowNumber, Int_t secNumber)
287 //Writes a trailer of 40 bits
290 AliError("No ALTRO mapping information is loaded! Filling a dummy trailer!");
291 return WriteDummyTrailer(wordsNumber,padNumber,
292 rowNumber,secNumber);
295 Int_t num = fFreeCellBuffer % 4;
296 for(Int_t i = 0; i < num; i++) {
303 temp |= ((wordsNumber & 0x3FF) >> 4);
305 temp = (wordsNumber << 6) & 0x3FF;
308 Short_t hwAdress = fMapping->GetHWAdress(rowNumber,padNumber,secNumber);
310 AliFatal(Form("No hardware (ALTRO) adress found for these pad-row (%d) and pad (%d) indeces !",rowNumber,padNumber));
312 temp |= (hwAdress >> 10) & 0x3;
314 temp = hwAdress & 0x3FF;
318 //_____________________________________________________________________________
319 Bool_t AliAltroBuffer::ReadDummyTrailer(Int_t& wordsNumber, Int_t& padNumber,
320 Int_t& rowNumber, Int_t& secNumber)
322 //Read a dummy trailer of 40 bits in the forward reading mode
324 wordsNumber = GetNext();
325 if (wordsNumber == -1) return kFALSE;
326 padNumber = GetNext();
327 if (padNumber == -1) return kFALSE;
328 rowNumber = GetNext();
329 if (rowNumber == -1) return kFALSE;
330 secNumber = GetNext();
331 if (secNumber == -1) return kFALSE;
335 //_____________________________________________________________________________
336 Bool_t AliAltroBuffer::ReadTrailer(Int_t& wordsNumber, Int_t& padNumber,
337 Int_t& rowNumber, Int_t& secNumber)
339 //Read a trailer of 40 bits in the forward reading mode
341 AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
342 return ReadDummyTrailer(wordsNumber,padNumber,
343 rowNumber,secNumber);
346 Int_t temp = GetNext();
348 AliFatal(Form("Incorrect trailer found ! Expecting 0x2AA but found %x !",temp));
351 if ((temp >> 6) != 0xA)
352 AliFatal(Form("Incorrect trailer found ! Expecting 0xA but found %x !",temp >> 6));
353 wordsNumber = (temp << 4) & 0x3FF;
356 wordsNumber |= (temp >> 6);
357 if ((temp & 0xF) != 0xA)
358 AliFatal(Form("Incorrect trailer found ! Expecting second 0xA but found %x !",temp >> 6));
359 Int_t hwAdress = (temp & 0x3) << 10;
364 rowNumber = fMapping->GetPadRow(hwAdress);
365 padNumber = fMapping->GetPad(hwAdress);
366 secNumber = fMapping->GetSector(hwAdress);
370 //_____________________________________________________________________________
371 Bool_t AliAltroBuffer::ReadTrailerBackward(Int_t& wordsNumber,
373 Int_t& rowNumber, Int_t& secNumber)
375 //Read a trailer of 40 bits in the backward reading mode
378 fEndingFillWords = 0;
380 temp = GetNextBackWord();
382 if (temp == -1) return kFALSE;
383 } while (temp == 0x2AA);
386 rowNumber = GetNextBackWord();
387 if (rowNumber == -1) return kFALSE;
388 padNumber = GetNextBackWord();
389 if (padNumber == -1) return kFALSE;
390 wordsNumber = GetNextBackWord();
391 if (wordsNumber == -1) return kFALSE;
396 //_____________________________________________________________________________
397 void AliAltroBuffer::WriteChannel(Int_t padNumber, Int_t rowNumber,
399 Int_t nTimeBins, const Int_t* adcValues,
402 //Write all ADC values and the trailer of a channel
406 Int_t bunchLength = 0;
408 // loop over time bins
409 for (Int_t iTime = 0; iTime < nTimeBins; iTime++) {
410 if (adcValues[iTime] >= threshold) { // ADC value above threshold
411 FillBuffer(adcValues[iTime]);
416 } else if (timeBin >= 0) { // end of bunch
418 FillBuffer(bunchLength + 2);
425 if (timeBin >= 0) { // end of bunch
427 FillBuffer(bunchLength + 2);
432 WriteTrailer(nWords, padNumber, rowNumber, secNumber);
436 //_____________________________________________________________________________
437 void AliAltroBuffer::WriteDataHeader(Bool_t dummy, Bool_t compressed)
439 //Write a (dummy or real) DDL data header,
440 //set the compression bit if compressed
442 AliRawDataHeader header;
444 //if size=0 it means that this data header is a dummy data header
445 fDataHeaderPos = fFile->tellp();
446 fFile->write((char*)(&header), sizeof(header));
448 UInt_t currentFilePos = fFile->tellp();
449 fFile->seekp(fDataHeaderPos);
450 header.fSize = currentFilePos-fDataHeaderPos;
451 header.SetAttribute(0); // valid data
452 if (compressed) header.SetAttribute(1);
453 fFile->write((char*)(&header), sizeof(header));
454 fFile->seekp(currentFilePos);
458 //_____________________________________________________________________________
459 Bool_t AliAltroBuffer::ReadDataHeader()
461 //Read the DDL data header at the beginning of the file,
462 //returns true in case of valid data
464 AliRawDataHeader header;
465 UInt_t currentPos = fFile->tellp();
467 if (!fFile->read((char*)(&header), sizeof(header))) return kFALSE;
468 fDataHeaderPos = fFile->tellp();
469 fFile->seekp(currentPos);
470 return header.TestAttribute(0);