Minor modification related to the new CASTOR stager
[u/mrichter/AliRoot.git] / RAW / AliAltroBuffer.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
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  **************************************************************************/
15
16 /* $Id$ */
17
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
22 // Author: D.Favretto
23
24 #include "AliAltroBuffer.h"
25 #include "AliRawDataHeader.h"
26 #include <Riostream.h>
27 #include <stdlib.h>
28
29
30 ClassImp(AliAltroBuffer)
31
32
33 //_____________________________________________________________________________
34 AliAltroBuffer::AliAltroBuffer(const char* fileName, Int_t flag):
35   fShift(0),
36   fCurrentCell(0),
37   fFreeCellBuffer(0),
38   fFlag(flag),
39   fVerbose(0),
40   fFile(NULL),
41   fMaskBackward(0xFF),
42   fFilePosition(0),
43   fFileEnd(0),
44   fDataHeaderPos(0),
45   fEndingFillWords(0)
46 {
47 //if flag = 1 the actual object is used in the write mode
48 //if flag = 0 the actual object is used in the read mode
49
50   //the buffer is cleaned 
51   for (Int_t i = 0; i < 5; i++) fBuffer[i] = 0;
52
53   if (flag) {
54     fFreeCellBuffer = 16;
55     fShift = 32; 
56     //open the output file
57 #ifndef __DECCXX
58     fFile = new fstream(fileName, ios::binary|ios::out);
59 #else
60     fFile = new fstream(fileName, ios::out);
61 #endif
62   } else {
63     //open the input file
64 #ifndef __DECCXX
65     fFile = new fstream(fileName, ios::binary|ios::in);
66 #else
67     fFile = new fstream(fileName, ios::in);
68 #endif
69     if (!fFile) {
70       Error("AliAltroBuffer", "File doesn't exist: %s", fileName);
71       return;
72     }
73     fShift = 0;
74     //To get the file dimension (position of the last element in term of bytes)
75     fFile->seekg(0, ios::end);
76     fFilePosition = fFile->tellg();
77     fFileEnd = fFilePosition;
78     fFile->seekg(0);
79   }
80 }
81
82 //_____________________________________________________________________________
83 AliAltroBuffer::~AliAltroBuffer()
84 {
85 // destructor
86
87   if (fFlag) {
88     //Flush out the Buffer content at the end only if Buffer wasn't completely filled
89     Flush();
90     if (fVerbose) Info("~AliAltroBuffer", "File Created");
91   }//end if
92   fFile->close();
93   delete fFile;
94 }
95
96 //_____________________________________________________________________________
97 AliAltroBuffer::AliAltroBuffer(const AliAltroBuffer& source):
98   TObject(source),
99   fShift(source.fShift),
100   fCurrentCell(source.fCurrentCell),
101   fFreeCellBuffer(source.fFreeCellBuffer),
102   fFlag(source.fFlag),
103   fVerbose(source.fVerbose),
104   fFile(NULL),
105   fMaskBackward(source.fMaskBackward),
106   fFilePosition(source.fFilePosition),
107   fFileEnd(source.fFileEnd),
108   fDataHeaderPos(source.fDataHeaderPos),
109   fEndingFillWords(source.fEndingFillWords)
110 {
111 // Copy Constructor
112
113   Fatal("AliAltroBuffer", "copy constructor not implemented");
114 }
115
116 //_____________________________________________________________________________
117 AliAltroBuffer& AliAltroBuffer::operator = (const AliAltroBuffer& /*source*/)
118 {
119 //Assigment operator
120
121   Fatal("operator =", "assignment operator not implemented");
122   return *this;
123 }
124
125
126 //_____________________________________________________________________________
127 Int_t AliAltroBuffer::GetNext()
128 {
129 //It reads a 10 bits word in forward dicection from the Buffer.
130 //A new Buffer is read from the file only when Buffer is empty.
131 //If there aren't elements anymore -1 is returned otherwise 
132 //the next element is returned
133
134   UInt_t mask = 0xFFC00000;
135   UInt_t temp;
136   UInt_t value;
137   if (!fShift) {
138     if (fFile->tellg() >= (Int_t)fFileEnd) return -1;
139     if (fFile->read((char*)fBuffer, sizeof(UInt_t)*5)) {
140       fCurrentCell = 0;
141       fShift = 22;
142       value = fBuffer[fCurrentCell] & mask;
143       value = value >> 22;
144       fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << 10;
145       return value;      
146     } else {
147       return -1;
148     }
149   } else {
150     if (fShift >= 10) {
151       value = fBuffer[fCurrentCell] & mask;
152       value = value >> 22;
153       fShift -= 10;
154       fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << 10;
155     } else {
156       value = fBuffer[fCurrentCell] & mask;
157       fCurrentCell++;
158       temp = fBuffer[fCurrentCell];
159       temp = temp >> fShift;
160       temp = temp & mask;
161       value = value | temp;
162       value = value >> 22;
163       fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << (10-fShift);
164       fShift += 22;
165     }
166     return value;
167   }//end else
168 }
169
170 //_____________________________________________________________________________
171 Int_t AliAltroBuffer::GetNextBackWord()
172 {
173 //It reads a 10 bits word in backward dicection from the Buffer.
174 //A new Buffer is read from the file only when Buffer is empty.
175 //If there aren't elements anymore -1 is returned otherwise 
176 //the next element is returned
177
178   UInt_t mask = 0x3FF;
179   UInt_t temp;
180   UInt_t value;
181   if (!fShift) {
182     if (fFilePosition > fDataHeaderPos){
183       fFilePosition -= sizeof(UInt_t)*5;
184       fFile->seekg(fFilePosition);
185       fFile->read((char*)fBuffer, sizeof(UInt_t)*5);
186       
187       fCurrentCell = 4;
188       fShift = 22;
189       fMaskBackward = 0xFF;
190       value = fBuffer[fCurrentCell] & mask;
191       fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> 10;
192       return value;
193     } else {
194       fFile->seekg(fDataHeaderPos);
195       return -1;
196     }
197   } else {
198     if (fShift >= 10) {
199       value = fBuffer[fCurrentCell] & mask;
200       fShift -= 10;
201       fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> 10;
202     } else {
203       value = fBuffer[fCurrentCell];
204       fCurrentCell--;
205       temp = fBuffer[fCurrentCell] & mask;
206       temp = temp & fMaskBackward;
207       fMaskBackward = fMaskBackward >> 2;
208       temp = temp << fShift;
209       value = value | temp;
210       fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> (10-fShift);
211       fShift = 22 + fShift;
212     }
213     return value;
214   }//end else
215 }
216
217 //_____________________________________________________________________________
218 void AliAltroBuffer::Flush()
219 {
220 // Flushes the Buffer content 
221   if (fFreeCellBuffer != 16) {
222     Int_t temp = fFreeCellBuffer;
223     for (Int_t i = 0; i < temp; i++){
224       FillBuffer(0x2AA);
225     }//end for
226   }//end if
227 }
228
229 //_____________________________________________________________________________
230 void AliAltroBuffer::FillBuffer(Int_t val)
231 {
232 //Fills the Buffer with 16 ten bits words and write into a file 
233
234   if ((val > 0x3FF) || (val < 0)) {
235     Error("FillBuffer", "Value out of range (10 bits): %d", val);
236     val = 0x3FF;
237   }
238   fFreeCellBuffer--;
239   if (fShift < 10) {
240     Int_t temp = val;
241     val = val >> (10-fShift);
242     fBuffer[fCurrentCell] |= val;
243     fCurrentCell++;
244     fShift += 32;
245     val = temp;
246   }
247   fShift -= 10;
248   val = val << fShift;
249   fBuffer[fCurrentCell] |= val;
250   if (!fShift) {
251     //Buffer is written into a file
252     fFile->write((char*)fBuffer, sizeof(UInt_t)*5);
253     //Buffer is empty
254     for (Int_t j = 0; j < 5; j++) fBuffer[j] = 0;
255     fShift = 32;
256     fCurrentCell = 0;
257     fFreeCellBuffer = 16;
258   }
259 }
260
261
262 //_____________________________________________________________________________
263 void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Int_t padNumber,
264                                   Int_t rowNumber, Int_t secNumber)
265 {
266 //Writes a trailer of 40 bits
267
268   Int_t num = fFreeCellBuffer % 4;
269   for(Int_t i = 0; i < num; i++) {
270     FillBuffer(0x2AA);
271   }//end for
272   FillBuffer(wordsNumber);
273   FillBuffer(padNumber);
274   FillBuffer(rowNumber);
275   FillBuffer(secNumber);
276 }
277
278 //_____________________________________________________________________________
279 Bool_t AliAltroBuffer::ReadTrailer(Int_t& wordsNumber, Int_t& padNumber,
280                                    Int_t& rowNumber, Int_t& secNumber)
281 {
282 //Read a trailer of 40 bits in the forward reading mode
283
284   wordsNumber = GetNext();
285   if (wordsNumber == -1) return kFALSE;
286   padNumber = GetNext();
287   if (padNumber == -1) return kFALSE;
288   rowNumber = GetNext();
289   if (rowNumber == -1) return kFALSE;
290   secNumber = GetNext();
291   if (secNumber == -1) return kFALSE;
292   return kTRUE;
293 }
294
295 //_____________________________________________________________________________
296 Bool_t AliAltroBuffer::ReadTrailerBackward(Int_t& wordsNumber, 
297                                            Int_t& padNumber,
298                                            Int_t& rowNumber, Int_t& secNumber)
299 {
300 //Read a trailer of 40 bits in the backward reading mode
301
302   Int_t temp;
303   fEndingFillWords = 0;
304   do {
305     temp = GetNextBackWord();
306     fEndingFillWords++;
307     if (temp == -1) return kFALSE;
308   } while (temp == 0x2AA);  
309   fEndingFillWords--;
310   secNumber = temp;
311   rowNumber = GetNextBackWord();
312   if (rowNumber == -1) return kFALSE;
313   padNumber = GetNextBackWord();
314   if (padNumber == -1) return kFALSE;
315   wordsNumber = GetNextBackWord();
316   if (wordsNumber == -1) return kFALSE;
317   return kTRUE;
318
319
320
321 //_____________________________________________________________________________
322 void AliAltroBuffer::WriteChannel(Int_t padNumber, Int_t rowNumber, 
323                                   Int_t secNumber,
324                                   Int_t nTimeBins, const Int_t* adcValues,
325                                   Int_t threshold)
326 {
327 //Write all ADC values and the trailer of a channel
328
329   Int_t nWords = 0;
330   Int_t timeBin = -1;
331   Int_t bunchLength = 0;
332
333   // loop over time bins
334   for (Int_t iTime = 0; iTime < nTimeBins; iTime++) {
335     if (adcValues[iTime] >= threshold) { // ADC value above threshold
336       FillBuffer(adcValues[iTime]);
337       nWords++;
338       timeBin = iTime;
339       bunchLength++;
340
341     } else if (timeBin >= 0) {  // end of bunch
342       FillBuffer(timeBin);
343       FillBuffer(bunchLength + 2);
344       nWords += 2;
345       timeBin = -1;
346       bunchLength = 0;
347     }
348   }
349
350   if (timeBin >= 0) {  // end of bunch
351     FillBuffer(timeBin);
352     FillBuffer(bunchLength + 2);
353     nWords += 2;
354   }
355
356   // write the trailer
357   WriteTrailer(nWords, padNumber, rowNumber, secNumber);
358 }
359
360
361 //_____________________________________________________________________________
362 void AliAltroBuffer::WriteDataHeader(Bool_t dummy, Bool_t compressed)
363 {
364 //Write a (dummy or real) DDL data header, 
365 //set the compression bit if compressed
366
367   AliRawDataHeader header;
368   if (dummy) {
369     //if size=0 it means that this data header is a dummy data header
370     fDataHeaderPos = fFile->tellp();
371     fFile->write((char*)(&header), sizeof(header));
372   } else {
373     UInt_t currentFilePos = fFile->tellp();
374     fFile->seekp(fDataHeaderPos);
375     header.fSize = currentFilePos-fDataHeaderPos;
376     header.SetAttribute(0);  // valid data
377     if (compressed) header.SetAttribute(1); 
378     fFile->write((char*)(&header), sizeof(header));
379     fFile->seekp(currentFilePos);
380   }
381 }
382
383 //_____________________________________________________________________________
384 Bool_t AliAltroBuffer::ReadDataHeader()
385 {
386 //Read the DDL data header at the beginning of the file, 
387 //returns true in case of valid data
388
389   AliRawDataHeader header;
390   UInt_t currentPos = fFile->tellp();
391   fFile->seekp(0);
392   if (!fFile->read((char*)(&header), sizeof(header))) return kFALSE;
393   fDataHeaderPos = fFile->tellp();
394   fFile->seekp(currentPos);
395   return header.TestAttribute(0);
396 }