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
23 #include "AliAltroBuffer.h"
24 #include "AliAltroMapping.h"
25 #include "AliRawDataHeader.h"
27 #include <Riostream.h>
31 ClassImp(AliAltroBuffer)
33 //_____________________________________________________________________________
34 AliAltroBuffer::AliAltroBuffer(const char* fileName, Int_t flag, const AliAltroMapping *mapping):
48 //if flag = 1 the actual object is used in the write mode
49 //if flag = 0 the actual object is used in the read mode
51 //the buffer is cleaned
52 for (Int_t i = 0; i < 5; i++) fBuffer[i] = 0;
57 //open the output file
59 fFile = new fstream(fileName, ios::binary|ios::out);
61 fFile = new fstream(fileName, ios::out);
66 fFile = new fstream(fileName, ios::binary|ios::in);
68 fFile = new fstream(fileName, ios::in);
71 Error("AliAltroBuffer", "File doesn't exist: %s", fileName);
75 //To get the file dimension (position of the last element in term of bytes)
76 fFile->seekg(0, ios::end);
77 fFilePosition = fFile->tellg();
78 fFileEnd = fFilePosition;
84 //_____________________________________________________________________________
85 AliAltroBuffer::~AliAltroBuffer()
90 //Flush out the Buffer content at the end only if Buffer wasn't completely filled
92 if (fVerbose) Info("~AliAltroBuffer", "File Created");
99 //_____________________________________________________________________________
100 AliAltroBuffer::AliAltroBuffer(const AliAltroBuffer& source):
102 fShift(source.fShift),
103 fCurrentCell(source.fCurrentCell),
104 fFreeCellBuffer(source.fFreeCellBuffer),
106 fVerbose(source.fVerbose),
108 fMaskBackward(source.fMaskBackward),
109 fFilePosition(source.fFilePosition),
110 fFileEnd(source.fFileEnd),
111 fDataHeaderPos(source.fDataHeaderPos),
112 fEndingFillWords(source.fEndingFillWords),
113 fMapping(source.fMapping)
117 Fatal("AliAltroBuffer", "copy constructor not implemented");
120 //_____________________________________________________________________________
121 AliAltroBuffer& AliAltroBuffer::operator = (const AliAltroBuffer& /*source*/)
125 Fatal("operator =", "assignment operator not implemented");
130 //_____________________________________________________________________________
131 Int_t AliAltroBuffer::GetNext()
133 //It reads a 10 bits word in forward dicection from the Buffer.
134 //A new Buffer is read from the file only when Buffer is empty.
135 //If there aren't elements anymore -1 is returned otherwise
136 //the next element is returned
138 UInt_t mask = 0xFFC00000;
142 if (fFile->tellg() >= (Int_t)fFileEnd) return -1;
143 if (fFile->read((char*)fBuffer, sizeof(UInt_t)*5)) {
146 value = fBuffer[fCurrentCell] & mask;
148 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << 10;
155 value = fBuffer[fCurrentCell] & mask;
158 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << 10;
160 value = fBuffer[fCurrentCell] & mask;
162 temp = fBuffer[fCurrentCell];
163 temp = temp >> fShift;
165 value = value | temp;
167 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << (10-fShift);
174 //_____________________________________________________________________________
175 Int_t AliAltroBuffer::GetNextBackWord()
177 //It reads a 10 bits word in backward dicection from the Buffer.
178 //A new Buffer is read from the file only when Buffer is empty.
179 //If there aren't elements anymore -1 is returned otherwise
180 //the next element is returned
186 if (fFilePosition > fDataHeaderPos){
187 fFilePosition -= sizeof(UInt_t)*5;
188 fFile->seekg(fFilePosition);
189 fFile->read((char*)fBuffer, sizeof(UInt_t)*5);
193 fMaskBackward = 0xFF;
194 value = fBuffer[fCurrentCell] & mask;
195 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> 10;
198 fFile->seekg(fDataHeaderPos);
203 value = fBuffer[fCurrentCell] & mask;
205 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> 10;
207 value = fBuffer[fCurrentCell];
209 temp = fBuffer[fCurrentCell] & mask;
210 temp = temp & fMaskBackward;
211 fMaskBackward = fMaskBackward >> 2;
212 temp = temp << fShift;
213 value = value | temp;
214 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> (10-fShift);
215 fShift = 22 + fShift;
221 //_____________________________________________________________________________
222 void AliAltroBuffer::Flush()
224 // Flushes the Buffer content
225 if (fFreeCellBuffer != 16) {
226 Int_t temp = fFreeCellBuffer;
227 for (Int_t i = 0; i < temp; i++){
233 //_____________________________________________________________________________
234 void AliAltroBuffer::FillBuffer(Int_t val)
236 //Fills the Buffer with 16 ten bits words and write into a file
238 if ((val > 0x3FF) || (val < 0)) {
239 Error("FillBuffer", "Value out of range (10 bits): %d", val);
245 val = val >> (10-fShift);
246 fBuffer[fCurrentCell] |= val;
253 fBuffer[fCurrentCell] |= val;
255 //Buffer is written into a file
256 fFile->write((char*)fBuffer, sizeof(UInt_t)*5);
258 for (Int_t j = 0; j < 5; j++) fBuffer[j] = 0;
261 fFreeCellBuffer = 16;
266 //_____________________________________________________________________________
267 void AliAltroBuffer::WriteDummyTrailer(Int_t wordsNumber, Int_t padNumber,
268 Int_t rowNumber, Int_t secNumber)
270 //Writes a trailer of 40 bits
272 Int_t num = fFreeCellBuffer % 4;
273 for(Int_t i = 0; i < num; i++) {
276 FillBuffer(wordsNumber);
277 FillBuffer(padNumber);
278 FillBuffer(rowNumber);
279 FillBuffer(secNumber);
282 //_____________________________________________________________________________
283 void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Int_t padNumber,
284 Int_t rowNumber, Int_t secNumber)
286 //Writes a trailer of 40 bits
289 AliError("No ALTRO mapping information is loaded! Filling a dummy trailer!");
290 return WriteDummyTrailer(wordsNumber,padNumber,
291 rowNumber,secNumber);
294 Short_t hwAddress = fMapping->GetHWAddress(rowNumber,padNumber,secNumber);
296 AliFatal(Form("No hardware (ALTRO) adress found for these pad-row (%d) and pad (%d) indeces !",rowNumber,padNumber));
297 WriteTrailer(wordsNumber,hwAddress);
300 //_____________________________________________________________________________
301 void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Short_t hwAddress)
303 //Writes a trailer of 40 bits using
304 //a given hardware adress
305 Int_t num = fFreeCellBuffer % 4;
306 for(Int_t i = 0; i < num; i++) {
310 temp = hwAddress & 0x3FF;
313 temp = (wordsNumber << 6) & 0x3FF;
315 temp |= ((hwAddress >> 10) & 0x3);
319 temp |= ((wordsNumber & 0x3FF) >> 4);
326 //_____________________________________________________________________________
327 Bool_t AliAltroBuffer::ReadDummyTrailer(Int_t& wordsNumber, Int_t& padNumber,
328 Int_t& rowNumber, Int_t& secNumber)
330 //Read a dummy trailer of 40 bits in the forward reading mode
332 wordsNumber = GetNext();
333 if (wordsNumber == -1) return kFALSE;
334 padNumber = GetNext();
335 if (padNumber == -1) return kFALSE;
336 rowNumber = GetNext();
337 if (rowNumber == -1) return kFALSE;
338 secNumber = GetNext();
339 if (secNumber == -1) return kFALSE;
343 //_____________________________________________________________________________
344 Bool_t AliAltroBuffer::ReadTrailer(Int_t& wordsNumber, Int_t& padNumber,
345 Int_t& rowNumber, Int_t& secNumber)
347 //Read a trailer of 40 bits in the forward reading mode
349 AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
350 return ReadDummyTrailer(wordsNumber,padNumber,
351 rowNumber,secNumber);
355 if (!ReadTrailer(wordsNumber,hwAddress)) return kFALSE;
356 rowNumber = fMapping->GetPadRow(hwAddress);
357 padNumber = fMapping->GetPad(hwAddress);
358 secNumber = fMapping->GetSector(hwAddress);
363 //_____________________________________________________________________________
364 Bool_t AliAltroBuffer::ReadTrailer(Int_t& wordsNumber, Short_t& hwAddress)
366 //Read a trailer of 40 bits in the forward reading mode
368 Int_t temp = GetNext();
372 wordsNumber = ((temp & 0x3FF) >> 6);
373 if (((temp >> 2) & 0xF) != 0xA)
374 AliFatal(Form("Incorrect trailer found ! Expecting second 0xA but found %x !",temp >> 6));
375 hwAddress |= (temp & 0x3) << 10;
378 if ((temp >> 6) != 0xA)
379 AliFatal(Form("Incorrect trailer found ! Expecting 0xA but found %x !",temp >> 6));
380 wordsNumber |= (temp << 4) & 0x3FF;
384 AliFatal(Form("Incorrect trailer found ! Expecting 0x2AA but found %x !",temp));
389 //_____________________________________________________________________________
390 Bool_t AliAltroBuffer::ReadDummyTrailerBackward(Int_t& wordsNumber, Int_t& padNumber,
391 Int_t& rowNumber, Int_t& secNumber)
393 //Read a trailer of 40 bits in the backward reading mode
396 fEndingFillWords = 0;
398 temp = GetNextBackWord();
400 if (temp == -1) return kFALSE;
401 } while (temp == 0x2AA);
404 rowNumber = GetNextBackWord();
405 if (rowNumber == -1) return kFALSE;
406 padNumber = GetNextBackWord();
407 if (padNumber == -1) return kFALSE;
408 wordsNumber = GetNextBackWord();
409 if (wordsNumber == -1) return kFALSE;
413 //_____________________________________________________________________________
414 Bool_t AliAltroBuffer::ReadTrailerBackward(Int_t& wordsNumber, Int_t& padNumber,
415 Int_t& rowNumber, Int_t& secNumber)
417 //Read a trailer of 40 bits in the backward reading mode
419 AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
420 return ReadDummyTrailerBackward(wordsNumber,padNumber,
421 rowNumber,secNumber);
425 if (!ReadTrailerBackward(wordsNumber,hwAddress)) return kFALSE;
426 rowNumber = fMapping->GetPadRow(hwAddress);
427 padNumber = fMapping->GetPad(hwAddress);
428 secNumber = fMapping->GetSector(hwAddress);
433 //_____________________________________________________________________________
434 Bool_t AliAltroBuffer::ReadTrailerBackward(Int_t& wordsNumber, Short_t& hwAddress)
436 //Read a trailer of 40 bits in the backward reading mode
439 fEndingFillWords = 0;
440 while ((temp = GetNextBackWord()) == 0x2AA) {
442 if (temp == -1) return kFALSE;
444 if (fEndingFillWords == 0)
445 AliFatal("Incorrect trailer found ! Expected 0x2AA not found !");
448 wordsNumber = (temp << 4) & 0x3FF;
449 if ((temp >> 6) != 0xA)
450 AliFatal(Form("Incorrect trailer found ! Expecting 0xA but found %x !",temp >> 6));
452 temp = GetNextBackWord();
453 hwAddress = (temp & 0x3) << 10;
454 if (((temp >> 2) & 0xF) != 0xA)
455 AliFatal(Form("Incorrect trailer found ! Expecting second 0xA but found %x !",(temp >> 2) & 0xF));
456 wordsNumber |= ((temp & 0x3FF) >> 6);
458 temp = GetNextBackWord();
464 //_____________________________________________________________________________
465 void AliAltroBuffer::WriteChannel(Int_t padNumber, Int_t rowNumber,
467 Int_t nTimeBins, const Int_t* adcValues,
470 //Write all ADC values and the trailer of a channel
471 Int_t nWords = WriteBunch(nTimeBins,adcValues,threshold);
473 WriteTrailer(nWords, padNumber, rowNumber, secNumber);
476 //_____________________________________________________________________________
477 void AliAltroBuffer::WriteChannel(Short_t hwAddress,
478 Int_t nTimeBins, const Int_t* adcValues,
481 //Write all ADC values and the trailer of a channel
482 Int_t nWords = WriteBunch(nTimeBins,adcValues,threshold);
484 WriteTrailer(nWords, hwAddress);
487 //_____________________________________________________________________________
488 Int_t AliAltroBuffer::WriteBunch(Int_t nTimeBins, const Int_t* adcValues,
491 //Write all ADC values
492 //Return number of words written
496 Int_t bunchLength = 0;
498 // loop over time bins
499 for (Int_t iTime = 0; iTime < nTimeBins; iTime++) {
500 if (adcValues[iTime] >= threshold) { // ADC value above threshold
501 FillBuffer(adcValues[iTime]);
506 } else if (timeBin >= 0) { // end of bunch
508 FillBuffer(bunchLength + 2);
515 if (timeBin >= 0) { // end of bunch
517 FillBuffer(bunchLength + 2);
524 //_____________________________________________________________________________
525 void AliAltroBuffer::ReadChannelBackward(Int_t& padNumber, Int_t& rowNumber,
527 Int_t& nTimeBins, Int_t* adcValues)
529 //Read all ADC values and the trailer of a channel (in backward order)
532 if (!ReadTrailerBackward(wordsNumber,padNumber,
533 rowNumber,secNumber)) return;
534 return ReadBunchBackward(wordsNumber,nTimeBins,adcValues);
537 //_____________________________________________________________________________
538 void AliAltroBuffer::ReadChannelBackward(Short_t& hwAddress,
539 Int_t& nTimeBins, Int_t* adcValues)
541 //Read all ADC values and the trailer of a channel (in backward order)
544 if (!ReadTrailerBackward(wordsNumber,
546 return ReadBunchBackward(wordsNumber,nTimeBins,adcValues);
549 //_____________________________________________________________________________
550 void AliAltroBuffer::ReadBunchBackward(Int_t wordsNumber,
551 Int_t& nTimeBins, Int_t* adcValues)
553 if (wordsNumber < 0) return;
554 // Number of fill words
556 if ((wordsNumber % 4) == 0)
559 nFillWords = 4 - wordsNumber % 4;
560 // Read the fill words
561 for (Int_t i = 0; i < nFillWords; i++) {
562 Int_t temp = GetNextBackWord();
564 AliFatal(Form("Invalid fill word, expected 0x2AA, but got %X", temp));
568 Int_t lastWord = wordsNumber;
570 while (lastWord > 0) {
571 Int_t l = GetNextBackWord();
572 if (l < 0) AliFatal(Form("Bad bunch length (%d) !", l));
573 Int_t t = GetNextBackWord();
574 if (t < 0) AliFatal(Form("Bad bunch time (%d) !", t));
576 if (nTimeBins == -1) nTimeBins = t + 1;
577 for (Int_t i = 2; i < l; i++) {
578 Int_t amp = GetNextBackWord();
579 if (amp < 0) AliFatal(Form("Bad adc value (%X) !", amp));
580 adcValues[t - (i-2)] = amp;
587 //_____________________________________________________________________________
588 void AliAltroBuffer::WriteDataHeader(Bool_t dummy, Bool_t compressed)
590 //Write a (dummy or real) DDL data header,
591 //set the compression bit if compressed
593 AliRawDataHeader header;
595 //if size=0 it means that this data header is a dummy data header
596 fDataHeaderPos = fFile->tellp();
597 fFile->write((char*)(&header), sizeof(header));
599 UInt_t currentFilePos = fFile->tellp();
600 fFile->seekp(fDataHeaderPos);
601 header.fSize = currentFilePos-fDataHeaderPos;
602 header.SetAttribute(0); // valid data
603 if (compressed) header.SetAttribute(1);
604 fFile->write((char*)(&header), sizeof(header));
605 fFile->seekp(currentFilePos);
609 //_____________________________________________________________________________
610 Bool_t AliAltroBuffer::ReadDataHeader()
612 //Read the DDL data header at the beginning of the file,
613 //returns true in case of valid data
615 AliRawDataHeader header;
616 UInt_t currentPos = fFile->tellp();
618 if (!fFile->read((char*)(&header), sizeof(header))) return kFALSE;
619 fDataHeaderPos = fFile->tellp();
620 fFile->seekp(currentPos);
621 return header.TestAttribute(0);