AliTPCBuffer160 renamed to AliAltroBuffer and method WriteChannel added, new utility...
[u/mrichter/AliRoot.git] / RAW / AliAltroBuffer.cxx
CommitLineData
3ea47630 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
30ClassImp(AliAltroBuffer)
31
32
33//_____________________________________________________________________________
34AliAltroBuffer::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//_____________________________________________________________________________
83AliAltroBuffer::~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//_____________________________________________________________________________
97AliAltroBuffer::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//_____________________________________________________________________________
117AliAltroBuffer& AliAltroBuffer::operator = (const AliAltroBuffer& /*source*/)
118{
119//Assigment operator
120
121 Fatal("operator =", "assignment operator not implemented");
122 return *this;
123}
124
125
126//_____________________________________________________________________________
127Int_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//_____________________________________________________________________________
171Int_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//_____________________________________________________________________________
218void 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//_____________________________________________________________________________
230void 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//_____________________________________________________________________________
259void 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//_____________________________________________________________________________
275Bool_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//_____________________________________________________________________________
292Bool_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//_____________________________________________________________________________
318void 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//_____________________________________________________________________________
358void 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}