AliTPCBuffer160 renamed to AliAltroBuffer and method WriteChannel added, new utility...
[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   fFreeCellBuffer--;
235   if (fShift < 10) {
236     Int_t temp = val;
237     val = val >> (10-fShift);
238     fBuffer[fCurrentCell] |= val;
239     fCurrentCell++;
240     fShift += 32;
241     val = temp;
242   }
243   fShift -= 10;
244   val = val << fShift;
245   fBuffer[fCurrentCell] |= val;
246   if (!fShift) {
247     //Buffer is written into a file
248     fFile->write((char*)fBuffer, sizeof(UInt_t)*5);
249     //Buffer is empty
250     for (Int_t j = 0; j < 5; j++) fBuffer[j] = 0;
251     fShift = 32;
252     fCurrentCell = 0;
253     fFreeCellBuffer = 16;
254   }
255 }
256
257
258 //_____________________________________________________________________________
259 void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Int_t padNumber,
260                                   Int_t rowNumber, Int_t secNumber)
261 {
262 //Writes a trailer of 40 bits
263
264   Int_t num = fFreeCellBuffer % 4;
265   for(Int_t i = 0; i < num; i++) {
266     FillBuffer(0x2AA);
267   }//end for
268   FillBuffer(wordsNumber);
269   FillBuffer(padNumber);
270   FillBuffer(rowNumber);
271   FillBuffer(secNumber);
272 }
273
274 //_____________________________________________________________________________
275 Bool_t AliAltroBuffer::ReadTrailer(Int_t& wordsNumber, Int_t& padNumber,
276                                    Int_t& rowNumber, Int_t& secNumber)
277 {
278 //Read a trailer of 40 bits in the forward reading mode
279
280   wordsNumber = GetNext();
281   if (wordsNumber == -1) return kFALSE;
282   padNumber = GetNext();
283   if (padNumber == -1) return kFALSE;
284   rowNumber = GetNext();
285   if (rowNumber == -1) return kFALSE;
286   secNumber = GetNext();
287   if (secNumber == -1) return kFALSE;
288   return kTRUE;
289 }
290
291 //_____________________________________________________________________________
292 Bool_t AliAltroBuffer::ReadTrailerBackward(Int_t& wordsNumber, 
293                                            Int_t& padNumber,
294                                            Int_t& rowNumber, Int_t& secNumber)
295 {
296 //Read a trailer of 40 bits in the backward reading mode
297
298   Int_t temp;
299   fEndingFillWords = 0;
300   do {
301     temp = GetNextBackWord();
302     fEndingFillWords++;
303     if (temp == -1) return kFALSE;
304   } while (temp == 0x2AA);  
305   fEndingFillWords--;
306   secNumber = temp;
307   rowNumber = GetNextBackWord();
308   if (rowNumber == -1) return kFALSE;
309   padNumber = GetNextBackWord();
310   if (padNumber == -1) return kFALSE;
311   wordsNumber = GetNextBackWord();
312   if (wordsNumber == -1) return kFALSE;
313   return kTRUE;
314
315
316
317 //_____________________________________________________________________________
318 void AliAltroBuffer::WriteChannel(Int_t padNumber, Int_t rowNumber, 
319                                   Int_t secNumber,
320                                   Int_t nTimeBins, const Int_t* adcValues,
321                                   Int_t threshold)
322 {
323 //Write all ADC values and the trailer of a channel
324
325   Int_t nWords = 0;
326   Int_t timeBin = -1;
327   Int_t bunchLength = 0;
328
329   // loop over time bins
330   for (Int_t iTime = 0; iTime < nTimeBins; iTime++) {
331     if (adcValues[iTime] >= threshold) { // ADC value above threshold
332       FillBuffer(adcValues[iTime]);
333       nWords++;
334       timeBin = iTime;
335       bunchLength++;
336
337     } else if (timeBin >= 0) {  // end of bunch
338       FillBuffer(timeBin);
339       FillBuffer(bunchLength + 2);
340       nWords += 2;
341       timeBin = -1;
342       bunchLength = 0;
343     }
344   }
345
346   if (timeBin >= 0) {  // end of bunch
347     FillBuffer(timeBin);
348     FillBuffer(bunchLength + 2);
349     nWords += 2;
350   }
351
352   // write the trailer
353   WriteTrailer(nWords, padNumber, rowNumber, secNumber);
354 }
355
356
357 //_____________________________________________________________________________
358 void AliAltroBuffer::WriteDataHeader(Bool_t dummy, Bool_t compressed)
359 {
360 //Write a (dummy or real) DDL data header, 
361 //set the compression bit if compressed
362
363   AliRawDataHeader header;
364   if (dummy) {
365     //if size=0 it means that this data header is a dummy data header
366     fDataHeaderPos = fFile->tellp();
367     fFile->write((char*)(&header), sizeof(header));
368   } else {
369     UInt_t currentFilePos = fFile->tellp();
370     fFile->seekp(fDataHeaderPos);
371     header.fSize = currentFilePos-fDataHeaderPos;
372     header.SetAttribute(0);  // valid data
373     if (compressed) header.SetAttribute(1); 
374     fFile->write((char*)(&header), sizeof(header));
375     fFile->seekp(currentFilePos);
376   }
377 }