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 Short_t hwAdress = fMapping->GetHWAdress(rowNumber,padNumber,secNumber);
297 AliFatal(Form("No hardware (ALTRO) adress found for these pad-row (%d) and pad (%d) indeces !",rowNumber,padNumber));
298 WriteTrailer(wordsNumber,hwAdress);
301 //_____________________________________________________________________________
302 void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Short_t hwAdress)
304 //Writes a trailer of 40 bits using
305 //a given hardware adress
306 Int_t num = fFreeCellBuffer % 4;
307 for(Int_t i = 0; i < num; i++) {
314 temp |= ((wordsNumber & 0x3FF) >> 4);
316 temp = (wordsNumber << 6) & 0x3FF;
319 temp |= (hwAdress >> 10) & 0x3;
321 temp = hwAdress & 0x3FF;
325 //_____________________________________________________________________________
326 Bool_t AliAltroBuffer::ReadDummyTrailer(Int_t& wordsNumber, Int_t& padNumber,
327 Int_t& rowNumber, Int_t& secNumber)
329 //Read a dummy trailer of 40 bits in the forward reading mode
331 wordsNumber = GetNext();
332 if (wordsNumber == -1) return kFALSE;
333 padNumber = GetNext();
334 if (padNumber == -1) return kFALSE;
335 rowNumber = GetNext();
336 if (rowNumber == -1) return kFALSE;
337 secNumber = GetNext();
338 if (secNumber == -1) return kFALSE;
342 //_____________________________________________________________________________
343 Bool_t AliAltroBuffer::ReadTrailer(Int_t& wordsNumber, Int_t& padNumber,
344 Int_t& rowNumber, Int_t& secNumber)
346 //Read a trailer of 40 bits in the forward reading mode
348 AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
349 return ReadDummyTrailer(wordsNumber,padNumber,
350 rowNumber,secNumber);
354 if (!ReadTrailer(wordsNumber,hwAdress)) return kFALSE;
355 rowNumber = fMapping->GetPadRow(hwAdress);
356 padNumber = fMapping->GetPad(hwAdress);
357 secNumber = fMapping->GetSector(hwAdress);
362 //_____________________________________________________________________________
363 Bool_t AliAltroBuffer::ReadTrailer(Int_t& wordsNumber, Short_t& hwAdress)
365 //Read a trailer of 40 bits in the forward reading mode
367 Int_t temp = GetNext();
369 AliFatal(Form("Incorrect trailer found ! Expecting 0x2AA but found %x !",temp));
372 if ((temp >> 6) != 0xA)
373 AliFatal(Form("Incorrect trailer found ! Expecting 0xA but found %x !",temp >> 6));
374 wordsNumber = (temp << 4) & 0x3FF;
377 wordsNumber |= (temp >> 6);
378 if (((temp >> 2) & 0xF) != 0xA)
379 AliFatal(Form("Incorrect trailer found ! Expecting second 0xA but found %x !",temp >> 6));
380 hwAdress = (temp & 0x3) << 10;
388 //_____________________________________________________________________________
389 Bool_t AliAltroBuffer::ReadDummyTrailerBackward(Int_t& wordsNumber, Int_t& padNumber,
390 Int_t& rowNumber, Int_t& secNumber)
392 //Read a trailer of 40 bits in the backward reading mode
395 fEndingFillWords = 0;
397 temp = GetNextBackWord();
399 if (temp == -1) return kFALSE;
400 } while (temp == 0x2AA);
403 rowNumber = GetNextBackWord();
404 if (rowNumber == -1) return kFALSE;
405 padNumber = GetNextBackWord();
406 if (padNumber == -1) return kFALSE;
407 wordsNumber = GetNextBackWord();
408 if (wordsNumber == -1) return kFALSE;
412 //_____________________________________________________________________________
413 Bool_t AliAltroBuffer::ReadTrailerBackward(Int_t& wordsNumber, Int_t& padNumber,
414 Int_t& rowNumber, Int_t& secNumber)
416 //Read a trailer of 40 bits in the backward reading mode
418 AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
419 return ReadDummyTrailerBackward(wordsNumber,padNumber,
420 rowNumber,secNumber);
424 if (!ReadTrailerBackward(wordsNumber,hwAdress)) return kFALSE;
425 rowNumber = fMapping->GetPadRow(hwAdress);
426 padNumber = fMapping->GetPad(hwAdress);
427 secNumber = fMapping->GetSector(hwAdress);
432 //_____________________________________________________________________________
433 Bool_t AliAltroBuffer::ReadTrailerBackward(Int_t& wordsNumber, Short_t& hwAdress)
435 //Read a trailer of 40 bits in the backward reading mode
438 fEndingFillWords = 0;
440 temp = GetNextBackWord();
442 if (temp == -1) return kFALSE;
443 } while (temp == 0x2AA);
448 temp = GetNextBackWord();
449 hwAdress |= (temp & 0x3) << 10;
450 if (((temp >> 2) & 0xF) != 0xA)
451 AliFatal(Form("Incorrect trailer found ! Expecting second 0xA but found %x !",temp >> 6));
452 wordsNumber = (temp >> 6);
454 temp = GetNextBackWord();
455 wordsNumber |= (temp << 4) & 0x3FF;
456 if ((temp >> 6) != 0xA)
457 AliFatal(Form("Incorrect trailer found ! Expecting 0xA but found %x !",temp >> 6));
459 temp = GetNextBackWord();
461 AliFatal(Form("Incorrect trailer found ! Expecting 0x2AA but found %x !",temp));
466 //_____________________________________________________________________________
467 void AliAltroBuffer::WriteChannel(Int_t padNumber, Int_t rowNumber,
469 Int_t nTimeBins, const Int_t* adcValues,
472 //Write all ADC values and the trailer of a channel
476 Int_t bunchLength = 0;
478 // loop over time bins
479 for (Int_t iTime = 0; iTime < nTimeBins; iTime++) {
480 if (adcValues[iTime] >= threshold) { // ADC value above threshold
481 FillBuffer(adcValues[iTime]);
486 } else if (timeBin >= 0) { // end of bunch
488 FillBuffer(bunchLength + 2);
495 if (timeBin >= 0) { // end of bunch
497 FillBuffer(bunchLength + 2);
502 WriteTrailer(nWords, padNumber, rowNumber, secNumber);
505 //_____________________________________________________________________________
506 void AliAltroBuffer::ReadChannel(Int_t padNumber, Int_t rowNumber,
508 Int_t& nTimeBins, Int_t* adcValues)
510 //Read all ADC values and the trailer of a channel
513 if (!ReadTrailer(wordsNumber,padNumber,
514 rowNumber,secNumber)) return;
516 if (wordsNumber < 0) return;
517 // Number of fill words
519 if ((wordsNumber % 4) == 0)
522 nFillWords = 4 - wordsNumber % 4;
523 // Read the fill words
524 for (Int_t i = 0; i < nFillWords; i++) {
525 Int_t temp = GetNext();
527 AliFatal(Form("Invalid fill word, expected 0x2AA, but got %X", temp));
531 Int_t lastWord = wordsNumber;
533 while (lastWord > 0) {
535 if (l < 0) AliFatal(Form("Bad bunch length (%d) !", l));
537 if (t < 0) AliFatal(Form("Bad bunch time (%d) !", t));
539 if (nTimeBins == -1) nTimeBins = t + 1;
540 for (Int_t i = 2; i < l; i++) {
541 Int_t amp = GetNext();
542 if (amp < 0) AliFatal(Form("Bad adc value (%X) !", amp));
543 adcValues[t - (i-2)] = amp;
550 //_____________________________________________________________________________
551 void AliAltroBuffer::WriteDataHeader(Bool_t dummy, Bool_t compressed)
553 //Write a (dummy or real) DDL data header,
554 //set the compression bit if compressed
556 AliRawDataHeader header;
558 //if size=0 it means that this data header is a dummy data header
559 fDataHeaderPos = fFile->tellp();
560 fFile->write((char*)(&header), sizeof(header));
562 UInt_t currentFilePos = fFile->tellp();
563 fFile->seekp(fDataHeaderPos);
564 header.fSize = currentFilePos-fDataHeaderPos;
565 header.SetAttribute(0); // valid data
566 if (compressed) header.SetAttribute(1);
567 fFile->write((char*)(&header), sizeof(header));
568 fFile->seekp(currentFilePos);
572 //_____________________________________________________________________________
573 Bool_t AliAltroBuffer::ReadDataHeader()
575 //Read the DDL data header at the beginning of the file,
576 //returns true in case of valid data
578 AliRawDataHeader header;
579 UInt_t currentPos = fFile->tellp();
581 if (!fFile->read((char*)(&header), sizeof(header))) return kFALSE;
582 fDataHeaderPos = fFile->tellp();
583 fFile->seekp(currentPos);
584 return header.TestAttribute(0);