]> git.uio.no Git - u/mrichter/AliRoot.git/blame - RAW/AliAltroBuffer.cxx
New methods to read and write trailers. New method to read whole altro channel
[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"
5802cf2d 25#include "AliAltroMapping.h"
3ea47630 26#include "AliRawDataHeader.h"
5802cf2d 27#include "AliLog.h"
3ea47630 28#include <Riostream.h>
29#include <stdlib.h>
30
31
32ClassImp(AliAltroBuffer)
33
3ea47630 34//_____________________________________________________________________________
5802cf2d 35AliAltroBuffer::AliAltroBuffer(const char* fileName, Int_t flag, const AliAltroMapping *mapping):
3ea47630 36 fShift(0),
37 fCurrentCell(0),
38 fFreeCellBuffer(0),
39 fFlag(flag),
40 fVerbose(0),
41 fFile(NULL),
42 fMaskBackward(0xFF),
43 fFilePosition(0),
44 fFileEnd(0),
45 fDataHeaderPos(0),
5802cf2d 46 fEndingFillWords(0),
47 fMapping(mapping)
3ea47630 48{
49//if flag = 1 the actual object is used in the write mode
50//if flag = 0 the actual object is used in the read mode
51
52 //the buffer is cleaned
53 for (Int_t i = 0; i < 5; i++) fBuffer[i] = 0;
54
55 if (flag) {
56 fFreeCellBuffer = 16;
57 fShift = 32;
58 //open the output file
59#ifndef __DECCXX
60 fFile = new fstream(fileName, ios::binary|ios::out);
61#else
62 fFile = new fstream(fileName, ios::out);
63#endif
64 } else {
65 //open the input file
66#ifndef __DECCXX
67 fFile = new fstream(fileName, ios::binary|ios::in);
68#else
69 fFile = new fstream(fileName, ios::in);
70#endif
71 if (!fFile) {
72 Error("AliAltroBuffer", "File doesn't exist: %s", fileName);
73 return;
74 }
75 fShift = 0;
76 //To get the file dimension (position of the last element in term of bytes)
77 fFile->seekg(0, ios::end);
78 fFilePosition = fFile->tellg();
79 fFileEnd = fFilePosition;
80 fFile->seekg(0);
81 }
5802cf2d 82
3ea47630 83}
84
85//_____________________________________________________________________________
86AliAltroBuffer::~AliAltroBuffer()
87{
88// destructor
89
90 if (fFlag) {
91 //Flush out the Buffer content at the end only if Buffer wasn't completely filled
92 Flush();
93 if (fVerbose) Info("~AliAltroBuffer", "File Created");
94 }//end if
95 fFile->close();
96 delete fFile;
5802cf2d 97
3ea47630 98}
99
100//_____________________________________________________________________________
101AliAltroBuffer::AliAltroBuffer(const AliAltroBuffer& source):
102 TObject(source),
103 fShift(source.fShift),
104 fCurrentCell(source.fCurrentCell),
105 fFreeCellBuffer(source.fFreeCellBuffer),
106 fFlag(source.fFlag),
107 fVerbose(source.fVerbose),
108 fFile(NULL),
109 fMaskBackward(source.fMaskBackward),
110 fFilePosition(source.fFilePosition),
111 fFileEnd(source.fFileEnd),
112 fDataHeaderPos(source.fDataHeaderPos),
5802cf2d 113 fEndingFillWords(source.fEndingFillWords),
114 fMapping(source.fMapping)
3ea47630 115{
116// Copy Constructor
117
118 Fatal("AliAltroBuffer", "copy constructor not implemented");
119}
120
121//_____________________________________________________________________________
122AliAltroBuffer& AliAltroBuffer::operator = (const AliAltroBuffer& /*source*/)
123{
124//Assigment operator
125
126 Fatal("operator =", "assignment operator not implemented");
127 return *this;
128}
129
130
131//_____________________________________________________________________________
132Int_t AliAltroBuffer::GetNext()
133{
134//It reads a 10 bits word in forward dicection from the Buffer.
135//A new Buffer is read from the file only when Buffer is empty.
136//If there aren't elements anymore -1 is returned otherwise
137//the next element is returned
138
139 UInt_t mask = 0xFFC00000;
140 UInt_t temp;
141 UInt_t value;
142 if (!fShift) {
143 if (fFile->tellg() >= (Int_t)fFileEnd) return -1;
144 if (fFile->read((char*)fBuffer, sizeof(UInt_t)*5)) {
145 fCurrentCell = 0;
146 fShift = 22;
147 value = fBuffer[fCurrentCell] & mask;
148 value = value >> 22;
149 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << 10;
150 return value;
151 } else {
152 return -1;
153 }
154 } else {
155 if (fShift >= 10) {
156 value = fBuffer[fCurrentCell] & mask;
157 value = value >> 22;
158 fShift -= 10;
159 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << 10;
160 } else {
161 value = fBuffer[fCurrentCell] & mask;
162 fCurrentCell++;
163 temp = fBuffer[fCurrentCell];
164 temp = temp >> fShift;
165 temp = temp & mask;
166 value = value | temp;
167 value = value >> 22;
168 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << (10-fShift);
169 fShift += 22;
170 }
171 return value;
172 }//end else
173}
174
175//_____________________________________________________________________________
176Int_t AliAltroBuffer::GetNextBackWord()
177{
178//It reads a 10 bits word in backward dicection from the Buffer.
179//A new Buffer is read from the file only when Buffer is empty.
180//If there aren't elements anymore -1 is returned otherwise
181//the next element is returned
182
183 UInt_t mask = 0x3FF;
184 UInt_t temp;
185 UInt_t value;
186 if (!fShift) {
187 if (fFilePosition > fDataHeaderPos){
188 fFilePosition -= sizeof(UInt_t)*5;
189 fFile->seekg(fFilePosition);
190 fFile->read((char*)fBuffer, sizeof(UInt_t)*5);
191
192 fCurrentCell = 4;
193 fShift = 22;
194 fMaskBackward = 0xFF;
195 value = fBuffer[fCurrentCell] & mask;
196 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> 10;
197 return value;
198 } else {
199 fFile->seekg(fDataHeaderPos);
200 return -1;
201 }
202 } else {
203 if (fShift >= 10) {
204 value = fBuffer[fCurrentCell] & mask;
205 fShift -= 10;
206 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> 10;
207 } else {
208 value = fBuffer[fCurrentCell];
209 fCurrentCell--;
210 temp = fBuffer[fCurrentCell] & mask;
211 temp = temp & fMaskBackward;
212 fMaskBackward = fMaskBackward >> 2;
213 temp = temp << fShift;
214 value = value | temp;
215 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> (10-fShift);
216 fShift = 22 + fShift;
217 }
218 return value;
219 }//end else
220}
221
222//_____________________________________________________________________________
223void AliAltroBuffer::Flush()
224{
225// Flushes the Buffer content
226 if (fFreeCellBuffer != 16) {
227 Int_t temp = fFreeCellBuffer;
228 for (Int_t i = 0; i < temp; i++){
229 FillBuffer(0x2AA);
230 }//end for
231 }//end if
232}
233
234//_____________________________________________________________________________
235void AliAltroBuffer::FillBuffer(Int_t val)
236{
237//Fills the Buffer with 16 ten bits words and write into a file
238
23b19451 239 if ((val > 0x3FF) || (val < 0)) {
240 Error("FillBuffer", "Value out of range (10 bits): %d", val);
241 val = 0x3FF;
242 }
3ea47630 243 fFreeCellBuffer--;
244 if (fShift < 10) {
245 Int_t temp = val;
246 val = val >> (10-fShift);
247 fBuffer[fCurrentCell] |= val;
248 fCurrentCell++;
249 fShift += 32;
250 val = temp;
251 }
252 fShift -= 10;
253 val = val << fShift;
254 fBuffer[fCurrentCell] |= val;
255 if (!fShift) {
256 //Buffer is written into a file
257 fFile->write((char*)fBuffer, sizeof(UInt_t)*5);
258 //Buffer is empty
259 for (Int_t j = 0; j < 5; j++) fBuffer[j] = 0;
260 fShift = 32;
261 fCurrentCell = 0;
262 fFreeCellBuffer = 16;
263 }
264}
265
266
5802cf2d 267//_____________________________________________________________________________
268void AliAltroBuffer::WriteDummyTrailer(Int_t wordsNumber, Int_t padNumber,
269 Int_t rowNumber, Int_t secNumber)
270{
271//Writes a trailer of 40 bits
272
273 Int_t num = fFreeCellBuffer % 4;
274 for(Int_t i = 0; i < num; i++) {
275 FillBuffer(0x2AA);
276 }//end for
277 FillBuffer(wordsNumber);
278 FillBuffer(padNumber);
279 FillBuffer(rowNumber);
280 FillBuffer(secNumber);
281}
282
3ea47630 283//_____________________________________________________________________________
284void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Int_t padNumber,
285 Int_t rowNumber, Int_t secNumber)
286{
287//Writes a trailer of 40 bits
288
5802cf2d 289 if (!fMapping) {
290 AliError("No ALTRO mapping information is loaded! Filling a dummy trailer!");
291 return WriteDummyTrailer(wordsNumber,padNumber,
292 rowNumber,secNumber);
293 }
294
20daa34d 295 Short_t hwAdress = fMapping->GetHWAdress(rowNumber,padNumber,secNumber);
296 if (hwAdress == -1)
297 AliFatal(Form("No hardware (ALTRO) adress found for these pad-row (%d) and pad (%d) indeces !",rowNumber,padNumber));
298 WriteTrailer(wordsNumber,hwAdress);
299}
300
301//_____________________________________________________________________________
302void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Short_t hwAdress)
303{
304//Writes a trailer of 40 bits using
305//a given hardware adress
3ea47630 306 Int_t num = fFreeCellBuffer % 4;
307 for(Int_t i = 0; i < num; i++) {
308 FillBuffer(0x2AA);
309 }//end for
5802cf2d 310 Int_t temp;
311 temp = 0x2AA;
312 FillBuffer(temp);
313 temp = 0xA << 6;
16e29964 314 temp |= ((wordsNumber & 0x3FF) >> 4);
5802cf2d 315 FillBuffer(temp);
316 temp = (wordsNumber << 6) & 0x3FF;
317 temp |= (0xA << 2);
318
5802cf2d 319 temp |= (hwAdress >> 10) & 0x3;
320 FillBuffer(temp);
321 temp = hwAdress & 0x3FF;
322 FillBuffer(temp);
3ea47630 323}
324
325//_____________________________________________________________________________
16e29964 326Bool_t AliAltroBuffer::ReadDummyTrailer(Int_t& wordsNumber, Int_t& padNumber,
327 Int_t& rowNumber, Int_t& secNumber)
3ea47630 328{
16e29964 329//Read a dummy trailer of 40 bits in the forward reading mode
3ea47630 330
331 wordsNumber = GetNext();
332 if (wordsNumber == -1) return kFALSE;
333 padNumber = GetNext();
334 if (padNumber == -1) return kFALSE;
335 rowNumber = GetNext();
336 if (rowNumber == -1) return kFALSE;
337 secNumber = GetNext();
338 if (secNumber == -1) return kFALSE;
339 return kTRUE;
340}
341
16e29964 342//_____________________________________________________________________________
343Bool_t AliAltroBuffer::ReadTrailer(Int_t& wordsNumber, Int_t& padNumber,
344 Int_t& rowNumber, Int_t& secNumber)
345{
346//Read a trailer of 40 bits in the forward reading mode
347 if (!fMapping) {
348 AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
349 return ReadDummyTrailer(wordsNumber,padNumber,
350 rowNumber,secNumber);
351 }
352
20daa34d 353 Short_t hwAdress;
354 if (!ReadTrailer(wordsNumber,hwAdress)) return kFALSE;
355 rowNumber = fMapping->GetPadRow(hwAdress);
356 padNumber = fMapping->GetPad(hwAdress);
357 secNumber = fMapping->GetSector(hwAdress);
358
359 return kTRUE;
360}
361
362//_____________________________________________________________________________
363Bool_t AliAltroBuffer::ReadTrailer(Int_t& wordsNumber, Short_t& hwAdress)
364{
365//Read a trailer of 40 bits in the forward reading mode
366
16e29964 367 Int_t temp = GetNext();
368 if (temp != 0x2AA)
369 AliFatal(Form("Incorrect trailer found ! Expecting 0x2AA but found %x !",temp));
370
371 temp = GetNext();
372 if ((temp >> 6) != 0xA)
373 AliFatal(Form("Incorrect trailer found ! Expecting 0xA but found %x !",temp >> 6));
374 wordsNumber = (temp << 4) & 0x3FF;
375
376 temp = GetNext();
377 wordsNumber |= (temp >> 6);
20daa34d 378 if (((temp >> 2) & 0xF) != 0xA)
16e29964 379 AliFatal(Form("Incorrect trailer found ! Expecting second 0xA but found %x !",temp >> 6));
20daa34d 380 hwAdress = (temp & 0x3) << 10;
16e29964 381
382 temp = GetNext();
383 hwAdress |= temp;
384
16e29964 385 return kTRUE;
386}
387
3ea47630 388//_____________________________________________________________________________
20daa34d 389Bool_t AliAltroBuffer::ReadDummyTrailerBackward(Int_t& wordsNumber, Int_t& padNumber,
390 Int_t& rowNumber, Int_t& secNumber)
3ea47630 391{
392//Read a trailer of 40 bits in the backward reading mode
393
394 Int_t temp;
395 fEndingFillWords = 0;
396 do {
397 temp = GetNextBackWord();
398 fEndingFillWords++;
399 if (temp == -1) return kFALSE;
400 } while (temp == 0x2AA);
401 fEndingFillWords--;
402 secNumber = temp;
403 rowNumber = GetNextBackWord();
404 if (rowNumber == -1) return kFALSE;
405 padNumber = GetNextBackWord();
406 if (padNumber == -1) return kFALSE;
407 wordsNumber = GetNextBackWord();
408 if (wordsNumber == -1) return kFALSE;
409 return kTRUE;
410}
411
20daa34d 412//_____________________________________________________________________________
413Bool_t AliAltroBuffer::ReadTrailerBackward(Int_t& wordsNumber, Int_t& padNumber,
414 Int_t& rowNumber, Int_t& secNumber)
415{
416//Read a trailer of 40 bits in the backward reading mode
417 if (!fMapping) {
418 AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
419 return ReadDummyTrailerBackward(wordsNumber,padNumber,
420 rowNumber,secNumber);
421 }
422
423 Short_t hwAdress;
424 if (!ReadTrailerBackward(wordsNumber,hwAdress)) return kFALSE;
425 rowNumber = fMapping->GetPadRow(hwAdress);
426 padNumber = fMapping->GetPad(hwAdress);
427 secNumber = fMapping->GetSector(hwAdress);
428
429 return kTRUE;
430}
431
432//_____________________________________________________________________________
433Bool_t AliAltroBuffer::ReadTrailerBackward(Int_t& wordsNumber, Short_t& hwAdress)
434{
435//Read a trailer of 40 bits in the backward reading mode
436
437 Int_t temp;
438 fEndingFillWords = 0;
439 do {
440 temp = GetNextBackWord();
441 fEndingFillWords++;
442 if (temp == -1) return kFALSE;
443 } while (temp == 0x2AA);
444 fEndingFillWords--;
445
446 hwAdress = temp;
447
448 temp = GetNextBackWord();
449 hwAdress |= (temp & 0x3) << 10;
450 if (((temp >> 2) & 0xF) != 0xA)
451 AliFatal(Form("Incorrect trailer found ! Expecting second 0xA but found %x !",temp >> 6));
452 wordsNumber = (temp >> 6);
453
454 temp = GetNextBackWord();
455 wordsNumber |= (temp << 4) & 0x3FF;
456 if ((temp >> 6) != 0xA)
457 AliFatal(Form("Incorrect trailer found ! Expecting 0xA but found %x !",temp >> 6));
458
459 temp = GetNextBackWord();
460 if (temp != 0x2AA)
461 AliFatal(Form("Incorrect trailer found ! Expecting 0x2AA but found %x !",temp));
462
463 return kTRUE;
464}
3ea47630 465
466//_____________________________________________________________________________
467void AliAltroBuffer::WriteChannel(Int_t padNumber, Int_t rowNumber,
468 Int_t secNumber,
469 Int_t nTimeBins, const Int_t* adcValues,
470 Int_t threshold)
471{
472//Write all ADC values and the trailer of a channel
473
474 Int_t nWords = 0;
475 Int_t timeBin = -1;
476 Int_t bunchLength = 0;
477
478 // loop over time bins
479 for (Int_t iTime = 0; iTime < nTimeBins; iTime++) {
480 if (adcValues[iTime] >= threshold) { // ADC value above threshold
481 FillBuffer(adcValues[iTime]);
482 nWords++;
483 timeBin = iTime;
484 bunchLength++;
485
486 } else if (timeBin >= 0) { // end of bunch
487 FillBuffer(timeBin);
488 FillBuffer(bunchLength + 2);
489 nWords += 2;
490 timeBin = -1;
491 bunchLength = 0;
492 }
493 }
494
495 if (timeBin >= 0) { // end of bunch
496 FillBuffer(timeBin);
497 FillBuffer(bunchLength + 2);
498 nWords += 2;
499 }
500
501 // write the trailer
502 WriteTrailer(nWords, padNumber, rowNumber, secNumber);
503}
504
20daa34d 505//_____________________________________________________________________________
506void AliAltroBuffer::ReadChannel(Int_t padNumber, Int_t rowNumber,
507 Int_t secNumber,
508 Int_t& nTimeBins, Int_t* adcValues)
509{
510//Read all ADC values and the trailer of a channel
511
512 Int_t wordsNumber;
513 if (!ReadTrailer(wordsNumber,padNumber,
514 rowNumber,secNumber)) return;
515
516 if (wordsNumber < 0) return;
517 // Number of fill words
518 Int_t nFillWords;
519 if ((wordsNumber % 4) == 0)
520 nFillWords = 0;
521 else
522 nFillWords = 4 - wordsNumber % 4;
523 // Read the fill words
524 for (Int_t i = 0; i < nFillWords; i++) {
525 Int_t temp = GetNext();
526 if (temp != 0x2AA)
527 AliFatal(Form("Invalid fill word, expected 0x2AA, but got %X", temp));
528 }
529
530 // Decoding
531 Int_t lastWord = wordsNumber;
532 nTimeBins = -1;
533 while (lastWord > 0) {
534 Int_t l = GetNext();
535 if (l < 0) AliFatal(Form("Bad bunch length (%d) !", l));
536 Int_t t = GetNext();
537 if (t < 0) AliFatal(Form("Bad bunch time (%d) !", t));
538 lastWord -= 2;
539 if (nTimeBins == -1) nTimeBins = t + 1;
540 for (Int_t i = 2; i < l; i++) {
541 Int_t amp = GetNext();
542 if (amp < 0) AliFatal(Form("Bad adc value (%X) !", amp));
543 adcValues[t - (i-2)] = amp;
544 lastWord--;
545 }
546 }
547
548}
3ea47630 549
550//_____________________________________________________________________________
551void AliAltroBuffer::WriteDataHeader(Bool_t dummy, Bool_t compressed)
552{
553//Write a (dummy or real) DDL data header,
554//set the compression bit if compressed
555
556 AliRawDataHeader header;
557 if (dummy) {
558 //if size=0 it means that this data header is a dummy data header
559 fDataHeaderPos = fFile->tellp();
560 fFile->write((char*)(&header), sizeof(header));
561 } else {
562 UInt_t currentFilePos = fFile->tellp();
563 fFile->seekp(fDataHeaderPos);
564 header.fSize = currentFilePos-fDataHeaderPos;
565 header.SetAttribute(0); // valid data
566 if (compressed) header.SetAttribute(1);
567 fFile->write((char*)(&header), sizeof(header));
568 fFile->seekp(currentFilePos);
569 }
570}
b0aef454 571
572//_____________________________________________________________________________
573Bool_t AliAltroBuffer::ReadDataHeader()
574{
575//Read the DDL data header at the beginning of the file,
576//returns true in case of valid data
577
578 AliRawDataHeader header;
579 UInt_t currentPos = fFile->tellp();
580 fFile->seekp(0);
581 if (!fFile->read((char*)(&header), sizeof(header))) return kFALSE;
582 fDataHeaderPos = fFile->tellp();
583 fFile->seekp(currentPos);
584 return header.TestAttribute(0);
585}
5802cf2d 586