]>
Commit | Line | Data |
---|---|---|
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 | ||
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 | ||
23b19451 | 234 | if ((val > 0x3FF) || (val < 0)) { |
235 | Error("FillBuffer", "Value out of range (10 bits): %d", val); | |
236 | val = 0x3FF; | |
237 | } | |
3ea47630 | 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 | } | |
b0aef454 | 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 | } |